web-dev-qa-db-fra.com

Angularjs - $ rootScope dans la fonction de lien de directive

Je pose cette question parce que je ne sais pas trop comment penser de rootscope comme une dépendance passée à des directives

J'ai une directive qui doit afficher des informations de $ rootScope ...

Je pensais que je devais passer le $ rootScope à une directive, mais lorsque j'écris une directive comme celle-ci, elle semble fonctionner.

.directive("myBar", function () {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

Quand dois-je faire cela?

.directive("myBar", function ($rootScope) {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

Puis-je et comment utiliser rootScope si j'en ai besoin dans la fonction de liaison de la directive - ou dois-je le faire dans le contrôleur de la directive?

.directive("myBar", function ($rootScope) {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    link: function (scope, element, attrs, rootScope) {
        rootScope.rsUser = { firstName: 'Joe' };
        rootScope.rsUser = { welcome: 'Welcome' };
    },
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

Mes données rootScope sont définies dans la fonction d'exécution

 .run(function ($rootScope) {

  $rootScope.rsLabels = { 
      welcome: 'Welcome'
  };

  $rootScope.rsUser = { 
     firstName: 'Joe'
  };
});

Merci!

47
GRowing

D'après mes expériences, il semble que puisque toutes les $ scopes hériteront du $ rootScope, vous pourrez accéder aux données qui y sont contenues sans le demander en tant que service, conformément aux règles d'héritage prototypiques javascript. Si vous définissez la propriété scope de votre directive sur false ou sur {}, vous constaterez que vous ne pouvez plus y accéder.

.directive("myBar", function($rootScope) {
    return {
        restrict: "E",
        scope: { /* Isolate scope, no $rootScope access anymore */ },
        transclude: true,
        replace: true,
        template: '<div>' + 
                  '<span ng-transclude></span>' + 
                  '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                  '</div>'
    };
});

Exemple: http://jsbin.com/bequy/1/edit

51
Mike Cheel

Vous pouvez faire de cette façon:

{{$root.rsLabels.welcome}}
66
karaxuna

Il n'est pas recommandé d'utiliser la portée racine pour définir et obtenir des propriétés dans votre application angular. Essayez d'utiliser $ cacheFactory, car vous pouvez ainsi mettre en cache certaines valeurs sur différentes requêtes. ( $ cacheFactory docs )

7
Kurt Du Bois

Parfois, je dois utiliser $ scope. $ Root:

app.directive('setOrdinal', function() {
  return {
    link: function($scope, $element, $attr) {

      var steps = $scope.$root.steps;

      $scope.$watch(setOrdinal, function(value) {
        if (value)
        {
          // steps code here
        }
      });
    }
  };
});

app.controller('stepController', ['$scope', '$rootScope', 'GetSteps', function ($scope, $rootScope, GetSteps) {
  var s = $scope;
  var r = $rootScope;

  s.initialize = function(id)
  {
    GetSteps.get({id: id}, function(resp){
      r.steps = resp.steps;
    });
  };
}]);
4
omikes

Après avoir travaillé sur cette même question pendant un certain temps, j'ai pensé qu'il valait la peine de noter quelque chose qui avait été négligé dans le premier post. Voici mon code original:

app.directive('countrymap', function() 
{
    return {
        link: function(scope, element, attrs) {
            scope.$watch("countryMap", function (newCountry, oldCountry) 
            {
                setTimeout( function() 
                {
                    //function body here    
                }, 100);
            })
        }
    };  
}]);

Mis à part la question plus philosophique de conception de savoir si vous devriez ou non même utiliser $ rootScope, il y a une chose manifestement erronée avec mon code ci-dessus qui, à mon avis, a été laissée de côté dans la solution de Mike - la référence à $ rootScope. Si vous êtes comme moi et que vous avez séparé vos fichiers de directives et de contrôleurs, vous devrez modifier votre code comme suit:

app.directive('countrymap', ['$rootScope', function($rootScope) 
{
    return {
        link: function(scope, element, attrs) {
            $rootScope.$watch("countryMap", function (newCountry, oldCountry) 
            {
                setTimeout( function() 
                { 
                    //function body here
                }, 100);
            })
        }
    };  
}]);

Cependant, il reste encore une question épineuse: puis-je atteindre le même objectif sans référencer $ rootScope dans la directive? En effet vous pouvez. Vous devez diffuser le changement dans la propriété $ rootScope de manière à informer efficacement tous les étendues enfants du changement et à surveiller ce changement dans la directive.

Manette:

$rootScope.countryMap = 'thiscountry_map';
$rootScope.$broadcast( "countryMapChanged", $rootScope.countryMap );

Directif:

app.directive('countrymapalt', [function() 
{
    return {
        link: function(scope, element, attrs) {
            scope.$on("countryMapChanged", function(event, map) 
            {
                setTimeout( function() 
                { 
                    //function body here
                }, 100);
            })
        }
    };  
}]);
3
user1991179

Une autre méthode consiste à créer un service et à accéder à ce dernier par $ rootScope et d’autres fonctions. Je l'ai fait comme ça à cause de mon environnement ...

app.service('myService', function ($rootScope) 
{
    this.removeItem = function (el) 
    {
       console.log('rootScope: ',$rootScope);
       return true;
    }
});


app.directive('draggable', function($document,myService) 
{
   return function(scope, element, attr) 
   {
        myService.removeItem({id:1})
   }
});

Si vous le pouvez, le meilleur moyen est la solution Mike. sinon, essayez ma solution.

1
Philip Enc