web-dev-qa-db-fra.com

Angularjs surveille les changements dans la portée des parents

J'écris une directive et je dois surveiller la portée parent pour un changement. Je ne sais pas si je fais cela de la manière préférée, mais cela ne fonctionne pas avec le code suivant:

  scope.$watch(scope.$parent.data.overlaytype,function() {
    console.log("Change Detected...");
  })

Il s'est connecté au chargement de la fenêtre, mais plus jamais, même lorsque le type de superposition est modifié.

Comment puis-je regarder overlaytype pour un changement?

Edit: voici l'intégralité de la directive. Je ne sais pas vraiment pourquoi je reçois une lunette enfant

/* Center overlays vertically directive */
aw.directive('center',function($window){
  return {
    restrict : "A",
    link : function(scope,elem,attrs){

      var resize = function() {
        var winHeight = $window.innerHeight - 90,
            overlayHeight = elem[0].offsetHeight,
            diff = (winHeight - overlayHeight) / 2;
            elem.css('top',diff+"px");
      };

      var watchForChange = function() {
        return scope.$parent.data.overlaytype;
      }
      scope.$watch(watchForChange,function() {
        $window.setTimeout(function() {
          resize();
        }, 1);
      })

      angular.element($window).bind('resize',function(e){
        console.log(scope.$parent.data.overlaytype)
        resize();
      });
    }
  };
});
43
wesbos

Vous devez avoir la propriété data sur votre portée enfant, les portées utilisent l'héritage prototypique entre les portées parent et enfant.

En outre, le premier argument attendu par la méthode $ watch est une expression ou une fonction à évaluer et non une valeur d'une variable. Vous devez donc l'envoyer à la place.

7
Naor Biton

Si vous souhaitez regarder une propriété d'une étendue parent, vous pouvez utiliser $watch méthode de la portée parent.

//intead of $scope.$watch(...)
$scope.$parent.$watch('property', function(value){/* ... */});

EDIT 2016: Ce qui précède devrait très bien fonctionner, mais ce n'est pas vraiment un design épuré. Essayez d'utiliser un directive ou un composant à la place et déclarez ses dépendances comme liaisons. Cela devrait conduire à de meilleures performances et à une conception plus propre.

73
Petr Peller

Je vous suggère d'utiliser la diffusion $ entre les contrôleurs pour effectuer cela, ce qui semble être davantage le moyen de communication angular entre les contrôleurs parent/enfant)

Le concept est simple, vous regardez la valeur dans le contrôleur parent, puis, lorsqu'une modification se produit, vous pouvez la diffuser et l'attraper dans le contrôleur enfant

Voici un violon qui le démontre: http://jsfiddle.net/DotDotDot/f733J/

La partie dans le contrôleur parent ressemble à ça:

$scope.$watch('overlaytype', function(newVal, oldVal){
    if(newVal!=oldVal)
        $scope.$broadcast('overlaychange',{"val":newVal})
});

et dans le contrôleur enfant:

$scope.$on('overlaychange', function(event, args){
    console.log("change detected")
    //any other action can be perfomed here
});

Bon point avec cette solution, si vous voulez regarder la modification dans un autre contrôleur enfant, vous pouvez simplement attraper le même événement

S'amuser

Edit: Je ne vous ai pas vu la dernière édition, mais ma solution fonctionne également pour la directive, j'ai mis à jour le violon précédent ( http://jsfiddle.net/DotDotDot/f733J/1/ )

J'ai modifié votre directive pour la forcer à créer une portée enfant et à créer un contrôleur:

directive('center',function($window){
  return {
    restrict : "A",
    scope:true,
    controller:function($scope){
        $scope.overlayChanged={"isChanged":"No","value":""};
        $scope.$on('overlaychange', function(event, args){
        console.log("change detected")
        //whatever you need to do

    });
  },
link : function(scope,elem,attrs){

  var resize = function() {
    var winHeight = $window.innerHeight - 90,
        overlayHeight = elem[0].offsetHeight,
        diff = (winHeight - overlayHeight) / 2;
        elem.css('top',diff+"px");
  };
  angular.element($window).bind('resize',function(e){
    console.log(scope.$parent.data.overlaytype)
    resize();
      });
    }
  };
});
22
DotDotDot

Si vous cherchez à regarder une variable de portée parent dans une portée enfant, vous pouvez ajouter true comme deuxième argument sur votre $watch. Cela déclenchera votre montre chaque fois que votre objet est modifié

$scope.$watch("searchContext", function (ctx) {
                ...
            }, true);
6
S. Ktifa

D'accord, cela m'a pris un peu de temps, voici mes deux cents, j'aime aussi l'option événement:

Violon mis à jour http://jsfiddle.net/enU5S/1/

Le HTML

<div ng-app="myApp" ng-controller="MyCtrl">
    <input type="text" model="model.someProperty"/>
    <div awesome-sauce some-data="model.someProperty"></div>
</div>

Le JS

angular.module("myApp", []).directive('awesomeSauce',function($window){
  return {
    restrict : "A",
      template: "<div>Ch-ch-ch-changes: {{count}} {{someData}}</div>",
      scope: {someData:"="},
      link : function(scope,elem,attrs){
        scope.count=0;
        scope.$watch("someData",function() {
            scope.count++;
        })
    }
  };
}).controller("MyCtrl", function($scope){
    $scope.model = {someProperty: "something here");
});

Ce que je montre ici, c'est que vous pouvez avoir une variable qui a une liaison bidirectionnelle entre l'enfant et le parent, mais ne nécessite pas que l'enfant atteigne son parent pour obtenir une propriété. La tendance à chercher des choses peut devenir folle si vous ajoutez un nouveau parent au-dessus de la directive.

Si vous tapez dans la case, cela mettra à jour le modèle sur le contrôleur, celui-ci est à son tour lié à la propriété de la directive, il sera donc mis à jour dans la directive. Dans la fonction de lien des directives, il a une configuration de surveillance, donc chaque fois que la variable de portée change, il incrémente un compteur.

En savoir plus sur la portée d'isoler et les différences entre l'utilisation de = @ ou & ici: http://www.egghead.io/

2
shaunhusain