Is there a way to watch for attribute changes caused from outside the angular world?

I am trying to understand the interactions between the angular world and the angular world.

Given the directive, it is declared as follows:

<dir1 id="d1" attr1="100"/> 

If the code outside of angular changes the directive like this:

 $("#d1").attr("attr1", 1000); 

How can a directive know that one of its attributes has changed?

+6
source share
2 answers

It would be best to make this change inside the directive. If for some reason this is not possible, then there are several options.

Outside the application, get a link to any DOM element in the application. Using this link, you can get a link to its area. You can use your element with id d1 . For instance:

 var domElement = document.getElementById('d1'); var scope = angular.element(domElement).scope(); 

Here are a few options:

Option 1

Change the model instead of directly changing the view. In the communication function, save the initial value of the attribute in the scope variable, for example:

 scope.myvalue = attrs.attr1; 

Then you can change the value outside the application (using the scope link above), for example:

 scope.$apply(function(){ scope.myvalue = 1000; console.log('attribute changed'); }); 

Here is the fiddle

Option 2

If a view is directly processed using jQuery, I don’t know how to use $observe , $watch or binding the selection to an attribute that will work, because they all bind to the attribute expression itself, only once, when the link function is first run. Changing the value will cause these bindings to fail. Thus, you will have the $watch attribute of the DOM element itself (and not through attrs ):

 scope.$watch(function(){ return $(el).attr('attr1'); // Set a watch on the actual DOM value }, function(newVal){ scope.message = newVal; }); 

Then you can change the value outside the application (using the scope link above), for example:

 scope.$apply(function(){ $("#d1").attr("attr1",1000); }); 

Here is the fiddle

+9
source

Use the Web Components library, such as x-tags Mozilla or Polymer from Google . This option works without a monologue call of $scope.$apply every time an attribute changes.

I use x tags because of their broader browser support. When defining a new custom tag (directive), you can set the lifecycle.attributeChanged option to a callback function that will fire whenever the argument changes.

White papers are not very helpful. But through trial and error and immersion in the code, I was able to figure out how it works.

The context of the callback function ( this object) is the element itself. The one whose attribute has changed. The callback can take three arguments:

  • name - attribute name,
  • oldValue and
  • newValue - they speak for themselves.

So, before the business:

Code

This will follow the change attribute:

 xtag.register('dir1', { lifecycle: { attributeChanged: function (attribute, changedFrom, changedTo) { // Find the element scope var scope = angular.element(this).scope(); // Update the scope if our attribute has changed scope.$apply(function () { if (attribute == 'attr1') scope.style = changedTo; }); } } }); 

The attributeChanged callback only works when the argument values ​​change. To get their initial values, you need to manually scan the batch. Typically, the easiest way is to define a directive:

 myApp.directive('dir1', function () { return { ... , link: function (scope, element, attributes) { scope.attr1 = element[0].getAttribute('attr1'); } }; }); 
+1
source

Source: https://habr.com/ru/post/947515/


All Articles