1

CODEPEN here: http://codepen.io/anon/pen/dGeNLK

I have a $http response like the following.

$http({
        method: 'GET',  
        url: _spPageContextInfo.webAbsoluteUrl + "/itemsSite/_api/web/lists/getByTitle('items')/items?$select=*",
        cache: true,
        headers: { "Accept": "application/json;odata=verbose" }
    }).success(function (data, status, headers, config) {
        $scope.items = data.d.results;          

    }).error(function (data, status, headers, config) {

    });

The results, of which there are usually between 50 and 100, look somewhat like this

      {
    name: 'Item One',
    desc: "Item 1 [ITEM:1]View 1[/ITEM] Item 1b [ITEM:1b]View 1b[/ITEM] Item 1c [ITEM:1c]View 1c[/ITEM]"
  },
  {
    name: 'Item Two',
    desc: "Item 2 [ITEM:2]View 2[/ITEM] Item 2b [ITEM:2b]View 2b[/ITEM] Item 2c [ITEM:2c]View 2c[/ITEM]"
  },
  {
    name: 'Item three',
    desc: "Item 3 [ITEM:3]View 3[/ITEM] Item 3b [ITEM:3b]View 3b[/ITEM] Item 3c [ITEM:3c]View 1c[/ITEM]"
  }

And are then displayed using an ng-repeat like.

< div ng-repeat="item in items">
    < div class="col-sm-12" ng-bind-html="item.details | filter:search">< /div>
< /div>

Inside each is a block of text which potentially contains multiple strings from an old system that resemble the following.

[item:id]item name[/item]

How would I transform the json so that any instances of the above string could be intercepted and transformed into a clickable modal link such as

< a ng-click="viewItemDetails('1a');" >View 1a< /a >

I cannot change the structure of the text blocks.

NOTE: I have asked a similar question before and the suggestions neither worked nor were very graspable.

0

1 Answer 1

1

One way to do it is to pre process your data. Something like this: (I'll post a link to working code soon)

$scope.items.map(function(n) {
  var str = n.desc,
      re = /\[ITEM:.*?\]/ig,
      found = str.match(re);
  found = found.map(function(m) {
    return m.split(':')[1].replace(']', '');
  });

  return n.items = found;
});

and then use the new "items" property in a nested ng-repeat:

<ul>
  <li ng-repeat="item in items" fixLinks>{{item.name}}
    <div>
      <span ng-repeat="n in item.items">
        Item {{n}} 
        <a href ng-click="viewItemDetails({{n}})">
          View {{n}}
        </a>&nbsp;
      </span>
    </div>
    <hr/>
  </li>
</ul>

Here's the codepen

UPDATE Here's a pen that does the replacement:

$scope.items.map(function(n) {
  var str = n.desc,
      re = /\[ITEM:(.*?)\]/ig,
      tpl = '<a href ng-click="$1">'
  str = str.replace(re, tpl);
  str = str.replace(/\[\/ITEM\]/ig, '</a>');
  return n.muDesc = str;
});

UPDATE #2 : Using directive, compiling and calling the controller scope method. This can probably be improved but hopefully it helps for now. Here's the updated pen

Directive code:

app.directive('fixLinks', function ($parse, $compile) {
  function replaceStr(str) {
    var re = /\[ITEM:(.*?)\]/ig,
        tpl = '<a href ng-click="click(\'$1\')">'
    str = str.replace(re, tpl);
    str = str.replace(/\[\/ITEM\]/ig, '</a>');
    return str;
  }

  return {
    scope: {
      text: '=',
      flClick: '&'
    },
    link: function(scope, element) {
      var el = angular.element('<span>' + replaceStr(scope.text) + '</span>');
      $compile(el)(scope);
      element.append(el);
      scope.click = function(id) {
        scope.flClick({id: id});
      }
    }
  };
});

Markup:

<ul>
  <li ng-repeat="item in items">
    <div>{{item.name}}</div>
    <div fix-links text="item.desc" fl-click="viewItemDetails(id)"></div>
    <hr/>
  </li>
</ul>
Sign up to request clarification or add additional context in comments.

4 Comments

Hi, thanks for the suggestion. I cannot change the structure of the text so this would not work for me.
@freeBSD What do you mean by "structure of the text"?
There can be large blocks (sometimes three paragraphs) of text with these tags sprinkled throughout. I need to retain the formatting and just swap the tags with hyperlinks as they are found. (I updated the codepen to show a string of text.)
@freeBSD I've updated the answer twice assuming the last update is what would be most helpful for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.