P
P
Pavel2014-08-25 23:04:55
Angular
Pavel, 2014-08-25 23:04:55

How to fix render error in angularjs when using directives?

I recently started learning angularjs and there was a situation with rendering.
html

<radiogroup>
    <radio checked>Option 1</radio>
    <radio>Option 2</radio>
</radiogroup>

js
var application = angular.module('application', []);
application.directive('radiogroup', function(){
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    controller: function($scope, $element) {
      var radios = $scope.radios = [];

      this.check = function(radio) {
        angular.forEach(radios, function(radio) {
          radio.checked = false;
        });
        radio.checked = true;
      }

      this.addToGroup = function(radio, checked) {
        if (checked) this.check(radio);
        radios.push(radio);
      };
    },
    template: '<div class="radiogroup" ng-transclude></div>',
    replace: true
  }
})

.directive('radio', function() {
  return {
    require: '^radiogroup',
    restrict: 'E',
    transclude: true,
    scope: {},
    link: function(scope, element, attrs, radiogroupCtrl) {
      radiogroupCtrl.addToGroup(scope, angular.isUndefined(attrs.checked) ? false : true);
      element.bind('click', function(){
        radiogroupCtrl.check(scope);
      });
    },
    template: '<div class="radio"  ng-class="{active: checked}" ng-transclude></div>',
    replace: true
  }
});

When the page loads, everything is replaced as it should (if the element was marked as checked, then it is replaced with a div with the active class), but if you start clicking on something else, nothing happens, however, if you look at the objects in the radios variable, then everything is there OK - the checked parameter changes to true/false as it should. Can't think of a reason why the DOM doesn't update after an element is clicked?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey, 2014-08-25
@PaulTMatik

Because the $digest loop doesn't run. Read something about how data-binding works in angularjs.
In short, for each asynchronous change to $scope, you need to run $digest or $apply. The difference is this: $digest starts updating only the current and child scopes. $apply updates all all all. therefore in such pieces it is better to use $apply.

element.bind('click', function(){
        scope.$apply(function () {
           radiogroupCtrl.check(scope);
        });
});

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question