Question

I've been stuck on that since a few hours (I'm not especially good in JS/Angular by the way) and also looked for answers, but couldn't find my way out, so here's my problem: I have a function which aim is to replace what it founds between brackets in a text by something else, the matter is that I think the function is running before AngularJS, and my text is called by AngularJS (sorry if I have troubles explaining it in english). So, I'm searching on how execute the fonction after, or Angular before. Here are the parts of the code needed

HTML:

<ul class="list">
    <li ng-repeat="prop in props" ng-class="cssPropState(prop.state)" ng-click="checkProp(prop)" replace-directive>
         <p class="txtProps">{{prop.value}}</p>
    </li>
</ul>

JS:

exo2.directive("replaceDirective", function(){
    return function (scope, elements, attrs){
            var mytext = document.getElementsByClass("txtProps");
            var pattern = /\[(.*?)\]/g;
            var results = mytext.firstChild.nodeValue.match(pattern);
            mytext = mytext.replace(results[0], "TEST1");
            mytext = mytext.replace(results[1], "TEST2");
    }
  }
)

The text is called by {{prop.value}} and already contains brackets. My issue is that results returns always null, because it can't find the text, because it has not been initialized by Angular yet. Hope my problem is understood, and hope someone will be nice enough to help me !

Thanks

Was it helpful?

Solution

Try to move replace-directive down to the <p id="txtProps">, like this:

<ul class="list">
    <li ng-repeat="prop in props" ng-class="cssPropState(prop.state)" ng-click="checkProp(prop)">
         <p id="txtProps" replace-directive>{{prop.value}}</p>
    </li>
</ul>

Now, the element of the link function is the p element, so the link function would look like:

exo2.directive("replaceDirective", function($timeout){
    return function (scope, element, attrs){
        $timeout(function() {
            var mytext = element.html();
            var pattern = /\[(.*?)\]/g;
            var results = mytext.match(pattern);
            mytext = montext.replace(results[0], "TEST1");
            mytext = montext.replace(results[1], "TEST2");
            element.html(mytext);
        });
    }
});

OTHER TIPS

Update: Best way to modify a text in {{}} expression is using filter.

You can define a filter like this:

exo2.filter('replaceFilter', function(){
    return function(input) {
       var pattern = /\[(.*?)\]/g;
       var result = input.match(pattern);
       var mytext;
       mytext = montext.replace(results[0], "TEST1"); // Here is something broken. montext is undefined. You need fix this.
       mytext = montext.replace(results[1], "TEST2");
       return mytext;
    }
});

Then, use filter in html

<ul class="list">
    <li ng-repeat="prop in props" ng-class="cssPropState(prop.state)" ng-click="checkProp(prop)">
        <p class="txtProps">{{prop.value | replaceFilter }}</p>
    </li>
</ul>

when you directive replaceDirective is compiled. the ng-repeat directive has not finished yet. So you should wait for its completion or find an children element in a $watch execution.

exo2.directive("replaceDirective", function(){
    return function (scope, element, attrs){
        scope.$watch({
           var mytext = element.children('.txtProps'); // use class not id
           if(mytext.length) {
              var pattern = /\[(.*?)\]/g;
              var results = mytext.text().match(pattern);
              mytext = montext.replace(results[0], "TEST1");
              mytext = montext.replace(results[1], "TEST2");
              element.html(mytext);
           }
        });

    }
});

PS: you shouldn't use id inside ng-repeat. id should be unique in document.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top