2014-11-12 9 views
2

OK это надуманный пример, но ...AngularJS Доступ Связанный контроллер Атрибут Из директивы

Скажем, у меня есть контроллер, как это:

app.controller('TestCtrl', function() { 
    this.testString; 
    this.otherString; 
}); 

И у меня есть шаблон:

<div ng-controller='TestCtrl as test'> 
    <input demo type='text' ng-model='test.testString'> 
    {{test.otherString}} 
</div> 

А то у меня есть директивы, как это:

app.directive('demo', function() { 
    return { 
     require:'ngModel', 
     link: function(scope, elem, attrs, ctrl) { 

      scope.$watch(attrs.ngModel, function(newVal) { 

       /* How do I get otherString without knowing the controller alias? 
        This works but is not good practice */ 
       scope.test.otherString = newVal + ' is cool!'; 

       /* This doesn't work, but would if the property was in scope 
        instead of the controller */ 
       scope[attrs.demo] = newVal + ' is cool!'; 
      }); 
     } 
    } 
}); 

Как получить другую строку, не зная псевдоним контроллера? Я мог бы просто разбить attrs.ngModel, чтобы получить его, но есть ли «угловой» способ получить собственность?

EDIT

Хотя этот пример не точно отражают проблемы, которые я имел с моим реальным сценарием, я выяснить, как получить свойство контроллера в функции связи, что позволяет мне обновить модель :

 link: function(scope, elem, attrs, ctrl) { 

      var otherString = scope.$eval(attrs.demo);    

      scope.$watch(attrs.ngModel, function(newVal) { 
       otherString = newVal + ' is cool!'; 
      } 
     } 
+0

Директивы действительно все о манипуляциях с DOM и не должны напрямую привязываться к контроллеру. Я понял, что это надуманный пример, но похоже, что ваша директива должна быть просто дочерним контроллером, поскольку она больше связана с областью действия, чем с DOM. – Bryant

ответ

3

директива должна иметь нулевое знание чего-либо вне себя. Если директива зависит от внешнего контроллера, определяющего какое-либо произвольное свойство, все будет очень легко ломаться.

Определение свойства «scope» в директиве позволяет вам предоставить явный API для привязки данных к директиве.

myModule.directive('demo', function() { 
    return { 
    scope: { 
     demoString: '=demo', 
    }, 
    link: function(scope, element, attrs) { 
     // You can access demoString here, or in a directive controller. 
     console.log(scope.demoString); 
    }   
    }; 
}); 

И шаблон

<div ng-controller='TestCtrl as test'> 
    <input demo="test.otherString" ng-model='test.testString'> 
    {{test.otherString}} 
</div> 

Это не только способ облегчения передачи данных или настройке привязки к директиве, но он является наиболее распространенным способом и должны охватывать большинство прецедентов.

+0

Спасибо, jelbourn. Я изучил этот вариант, но, к сожалению, мой тестовый пример не совсем соответствует тому, что я пытаюсь сделать, а именно расширению функциональности существующей директивы, объявляющей ее собственную изолированную область, поэтому, когда я пытаюсь сделать это в своей директиве, выдает ошибку. Я правильно помету ваш ответ, но любая идея о том, что делать в случае моего реального сценария? – spongessuck

+0

Я не уверен, что вы подразумеваете под «расширением функциональности по существующей директиве». Добавление поведения во время выполнения на основе какого-либо состояния программы или действия пользователя? – jelbourn

+0

Да, точно. Я выяснил, что я могу сделать, - обновит OP. – spongessuck

0

Если вы пытаетесь быть более угловатыми, как я бы просто использовать $ объем в контроллере и передать, что директивы, как так:

app.directive('demo', function() { 
    return { 
    scope: {strings: '='}, 
    link: function(scope, elem, attrs, ctrl) { 

     scope.$watch('strings.test', function(newVal) { 

      /* How do I get otherString without knowing the controller alias? */ 
      scope.strings.other = newVal + ' is cool!'; 

     }); 
    } 
} 
}); 

затем в HTML:

<div ng-controller='TestCtrl as test'> 
     <input demo type='text' strings="strings" ng-model="strings.test" /> 
     {{strings.other}} 
    </div> 

В контроллере вы бы назначить:

$scope.strings = { 
    test: '', 
    other: '' 
} 
+0

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

Смежные вопросы