Подтвердить что ты не робот

Angularjs - $rootScope в функции директивной ссылки

Я задаю этот вопрос, потому что я не совсем понимаю, как думать о корнеплодах, как зависимость, передаваемая директивам.

У меня есть директива, которая должна отображать некоторую информацию из $rootScope...

Мне показалось, что мне нужно передать директиву $rootScope в директиву, но когда я пишу такую ​​директиву, похоже, она работает.

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

Когда это нужно сделать?

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

Могу ли я и КАК использовать rootScope, если мне это нужно в функции ссылки директивы, или я должен делать это в контроллере директивы?

.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>'
}
})

Мои данные rootScope определены в функции запуска

 .run(function ($rootScope) {

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

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

Спасибо!

4b9b3361

Ответ 1

Из моих экспериментов\опыта кажется, что, поскольку все $scopes в конечном счете унаследованы от $rootScope, вы сможете получить доступ к данным на нем, не запрашивая его как услугу, следуя стандартным правилам наследования прототипов javascript. Если вы должны установить свойство scope в своей директиве на false или {}, вы обнаружите, что больше не можете его получить.

.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>'
    };
});

Пример: http://jsbin.com/bequy/1/edit

Ответ 2

Вы можете сделать так:

{{$root.rsLabels.welcome}}

Ответ 3

Не рекомендуется использовать корневую область для установки и получения свойств в вашем приложении angular. Попробуйте использовать $cacheFactory, так как вы можете также кэшировать некоторые значения по различным запросам. ($cacheFactory docs)

Ответ 4

После непродолжительного увольнения по этому же вопросу я подумал, что стоит отметить что-то, что пренебрегали в первом посте. Вот мой оригинальный код:

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

Помимо более философского вопроса о том, нужно ли вообще использовать $rootScope, есть один явно ошибочный факт с моим кодом выше, который, как мне кажется, остался без решения Майка - ссылкой на $rootScope. Если вы похожи на меня и разделили свои директивные и контрольные файлы, вам нужно будет изменить свой код следующим образом:

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

Тем не менее, есть еще один острый вопрос: могу ли я достичь той же цели, не ссылаясь на $rootScope в директиве? Действительно, вы можете. Вам необходимо передать это изменение в свойство $rootScope, эффективно разрешив всем дочерним областям информацию об изменении и наблюдая за этим изменением в директиве.

Контроллер:

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

Директива

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

Ответ 5

Иногда мне приходится использовать $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;
    });
  };
}]);

Ответ 6

Другой способ - создать службу и бросить эту службу на $rootScope и другие функции. Я сделал это так из-за своей среды...

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})
   }
});

Если вы можете, лучшим способом является решение Майка. если нет, попробуйте мое решение.