Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating scope variable from directive

The scope variables updated by the directive are not reflected where we have {{variable}} on the page, however they do show up as being updated in when I do console.log(scope).

<script>
    var demoApp = angular.module('demoApp', []);

    demoApp.controller('demoController', function demoController($scope) {
      $scope.myElementId ="abcd";
      $scope.updateVals = function() {
        $scope.myElementClass = "";
      };
    });

    demoApp.directive('demoSelect', function() {
      return {
        restrict: 'A',
        controller: 'demoController',
        link: function(scope, element, attrs, controller) {
          element.on("click", function(event) {
            event.stopImmediatePropagation();
            event.preventDefault();
            scope.ele = angular.element(event.target);
            angular.element(".selected").removeClass("selected");
            $(scope.ele).addClass("selected");
            var mm = $(scope.ele).get(0);
            scope.myElementId = $(scope.ele).attr("id");
            scope.myElementClass = $(scope.ele).attr("class");
            scope.myElementType = mm.tagName;
          });
        }
      };
    });
  </script>

Here is the plunker for it. What am I missing?

like image 500
Vikram Avatar asked Dec 16 '22 02:12

Vikram


1 Answers

There were a couple of errors in your demo:

  1. jQuery was loaded after Angular. You should always load jQuery before Angular, so the latter is aware of and can take advantage of the former.

  2. The automatic dash-delimited to camelCase convertion is applied only to directives, not the names of your apps or controllers. Thus, you should write demoApp and demoController, instead of demo-app and demo-controller in your HTML.

  3. You were calling some Angular-specific code (updating values in the Scope) from an non-Angular context (jQuery event callback), so in order for having the changes processed by Angular (and the results propagated to the view), you must enclose the relevant code into scope.$apply().

  4. (This is not an error technically, but): You were converting some jQuery objects to jQuery objects again. This instroduces unnecessary overhead and should be avoided.


Taking into account the above, your directive's link function's body should look something like this:

element.on('click' , function(evt) {
    evt.stopImmediatePropagation();
    evt.preventDefault();

    $('.selected').removeClass('selected');
    element.addClass('selected');
    scope.$apply(function () {
        scope.myElementId    = attrs.id;
        scope.myElementClass = attrs.class;
        scope.myElementType  = element.prop('tagName');
    });
});

See, also, this woking demo.

like image 157
gkalpak Avatar answered Jan 18 '23 22:01

gkalpak