1

I append some divs into my HTML page inside Angular controller:

jQuery("#mytag").after('<div ng-click="sayHi()">Hi</div>');

and sayHi method is an Angular Method inside controller:

$scope.sayHi = function () {
        alert("hi");
};

But ng-click inside these dynamically created Div's doesn't works! Why?

13
  • 7
    this is not the proper way to do dynamic HTML with angular. In angular, you should always program using your data, and never program using the DOM. Using JQuery like this is rarely necessary except in extreme edge cases, and when it is, it is recommended to be put in a directive, where it can be recompiled. Perhaps if you showed what you are trying to accomplish with the code, we can show "the angular way" to accomplish the task. Commented Jul 18, 2015 at 20:37
  • 1
    @Himmel why--problem is obvious. The new html isn't being compiled by angular Commented Jul 18, 2015 at 20:45
  • 1
    Aggree with @Claies, anyhow if you would like to pursue this bad practice anyway, you should tell angular to recompile the code after adding new nodes to the DOM, using $scope.apply(). Ofcourse you should be in angular context to do so. Commented Jul 18, 2015 at 20:45
  • 4
    If you really want to learn Angular try to stop thinking in jQuery terms. Ideally drop jQuery altogether. Commented Jul 18, 2015 at 20:48
  • 3
    @Fcoder sure can...use a directive to listen to scroll event...then push more data into data model, angular ng-repeat takes care of the DOM. Commented Jul 18, 2015 at 20:57

2 Answers 2

2

So instead of jQuery("#mytag").after('<div ng-click="sayHi()">Hi</div>');

You should have:

function myTag() {

    return {
        link: function(element) {
            element.after('<div ng-click="sayHi()">Hi</div>');
        }
    }
}
angular.module('yourModule').directive('myTag', myTag);

Then in your view, instead of doing something like:

<div id="mytag"></div>

You should have:

<my-tag></my-tag>   or   <div my-tag></div>

Update As @Claies points out this too is not a clean approach to a load more or infinite scroll.

I don't know the details of what you are trying to do, so I am going to make some assumptions.

Lets assume we know you only have about 100 records to display. The user probably only wants to see the first 20, but the user then should have the ability to see 20 more after that, and again... until all 100 records are displayed.

In this scenario, it would probably be ok to load all these records into the browser and filter them on the client side in Angular. Again, this may not be your situation. I don't know what you are tying to do.

So in your view you can have a filter that limits these to the first 20 records. Then have an action that increases the filter by 20 records. When the filter limit is greater or equal to the number of records, hide the view more button.

<div ng-repeat="record in vm.records | limitTo : vm.display">
    {{ record }}
</div>
<button ng-show="vm.enableLoadMore" ng-click="vm.showMore()">Load More</button>

In your controller for this view, using the controllerAs syntax:

function RecordsController() {

     this.records = [ . . . ]; // your records

     this.display = 20; // number of records to display

     var self = this;

     Object.defineProperty(this, 'enableLoadMore', { get: function() {
         return self.records >= self.display;
     }})
}

RecordsController.prototype.showMore = function() {
    this.display += 20;
}
Sign up to request clarification or add additional context in comments.

2 Comments

this will definitely work, and eliminates the jquery call (and the need for $compile or $scope.$apply()), but it is still the same poor design logic, just moved to a new location. It's still trying to program the DOM, instead of programming the data.
Ya sure. This is a contrived example. Ill update it with something more appropriate.
2

angular compiles html when it's initialised first time only ,, if you want to recompile it you can inject $compile service into your controller and use it like this

$compile(element)(scope)

but this is not a proper way to dynamically append elements in angular can you tell me what exactly are you trying to build??

Comments

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.