9

Обновление: Должно быть, это было что-то глупое в другой части кода. Теперь он работает, поэтому синтаксис bindToController в порядке.AngularJS 1.4 директивы: область применения, двустороннее связывание и bindToController

Мы используем AngularJS 1.4, который ввел директивы new way to use bindToController.

После совсем немного чтения (и, возможно, не все понимает), мы определили наши директивы, как это:

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: {}, 
     bindToController: { 
     address: '=' 
     }, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

Назвав его с другой точкой зрения, как это:

<md-address address="vm.address"></md-address> 

После определено ранее в контроллере вида:

vm.address = { 
    street: null, 
    countryCode: null, 
    cityCode: null, 
    postalCode: null 
    }; 

Ссылка на переменные в th е шаблон директивы, как это:

<md-input-container> 
    <label>{{'ADDRESSNUMBER' | translate}}</label> 
    <input type="number" ng-model="dir.address.streetNumber"> 
    </md-input-container> 

Мы провели 4 часа, пытаясь выяснить, почему наша директива не работает. Ну, он работал, но двухсторонняя привязка между контроллером и директивой не была, vm.address.street был безнадежно установлен на нуль.

Через некоторое время, мы просто пытались по-старому:

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: { 
     address: '=' 
     }, 
     bindToController: true, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

И это волшебно работал. Любая идея ПОЧЕМУ?

+0

Что вы нашли в своем шаблоне 'modules/address/address.html'? Если вы пытались ссылаться на 'vm' вообще в шаблоне, то это вызовет нулевую ошибку, поскольку' vm' не существует в рамках вашей директивы. Кроме того, если вы пытались просто привязать к 'address' в шаблоне директивы, это также не существовало бы, поскольку вы привязываете ваш контроллер как' dir', поэтому это должно быть 'dir.address' –

+0

In в шаблоне мы ссылались на элементы с 'dir':' '. Я отредактировал главный пост, чтобы прояснить это. Благодарю. – LeoLozes

+0

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

ответ

18

Update:

Благодаря reference to this blog post, мне нужно обновить свой ответ. Поскольку AngularJS 1,4 это действительно кажется, что вы можете использовать

scope: {}, 
bindToController: { 
    variable: '=' 
} 

, который будет делать (точно) то же самое, что и старый синтаксис:

scope: { 
    variable: '=' 
}, 
bindToController: true 

Полезные строки из исходного AngularJS кода, чтобы объяснить это поведение:

if (isObject(directive.scope)) { 
    if (directive.bindToController === true) { 
    bindings.bindToController = parseIsolateBindings(directive.scope, 
                directiveName, true); 
    bindings.isolateScope = {}; 
    } else { 
    bindings.isolateScope = parseIsolateBindings(directive.scope, 
               directiveName, false); 
    } 
} 
if (isObject(directive.bindToController)) { 
    bindings.bindToController = 
     parseIsolateBindings(directive.bindToController, directiveName, true); 
} 

Источник: AngularJS 1.4.0

Оригинальный ответ:

Надеюсь, я могу объяснить вам, почему это поведение вы испытали правильно и где вы пропустили понимание концепции привязки сферы.

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

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: {}, 
     bindToController: { 
     address: '=' 
     }, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

С scope: {}, вы создали изолированный объем (без какого-либо наследования) для mdAddress директивы. Это означает: данные не передаются между родительским контроллером и вашей директивой.

Имея это в виду, что касается вашего второго фрагмента кода:

<md-address address="vm.address"></md-address> 

vm.address из родительского контроллера/зрения будет назначен в качестве выражения для атрибута адреса директивы, а как вы определили изолированную сферу, прежде , данные не передаются в AddressController и поэтому недоступны в значении bindToController.

Давайте рассмотрим определение объекта scope как «какие данные будут переданы» и bindToController как «какие данные будут доступны в контроллере моего представления как объект».

Итак, теперь давайте посмотрим на последний (и рабочий фрагмент кода):

.directive('mdAddress', function mdAddress() { 
    var directive = { 
     restrict: 'EA', 
     scope: { 
     address: '=' 
     }, 
     bindToController: true, 
     templateUrl: 'modules/address/address.html', 
     controller: AddressController, 
     controllerAs: 'dir' 
    }; 

Там вы создали изолированную сферу, тоже, но на этот раз вы добавили атрибут address быть принят в качестве выражение. Итак, теперь address, который вы передали из представления во втором фрагменте, будет доступен в области контроллера. Теперь установка bindToController: true свяжет все свойства текущей области с контроллером (или, скорее, объект controllerAs). И теперь это работает так, как вы ожидаете, потому что данные будут переданы в область, и данные будут переданы в область шаблонов контроллера.

Этот краткий обзор помог вам лучше понять концепцию объектов определения scope и bindToController?

+0

Большое спасибо за ваш ответ! Это имеет смысл, и я полностью понимаю вторую часть вашего объяснения, но первая часть, по-видимому, буквально противоположна той статье, которую я связал (о новой функции bindToController). Специально, когда он говорит «Это означает, что мы можем переместить наш объем: {name: '='} пример привязки к нему, чтобы сделать его более явным, что привязки привязок на самом деле унаследованы и привязаны к контроллеру» и заменяет 'scope: { name: '='}, bindToController: true' с 'scope: {}, bindToController: {name: '='}'. – LeoLozes

+0

Действительно, спасибо за ваш ответ. Вы правы, мне нужно отменить части моего ответа. Важной линией является одна из исходного кода AngularJS, упомянутая в статье, поэтому в обоих случаях поведение должно быть одинаковым. Может, у вас действительно был какой-то странный ошибка/опечатка в вашем коде? Или вы можете воспроизвести все из своего вопроса? Очень интересная тема! – ConcurrentHashMap

+0

Спасибо, я подумал, что, возможно, неправильно понял статью :). В любом случае, просмотрев код AngularJS, может быть, что 'scope: {}' возвращает 'isObject' как true, так как это пустой объект, а не' null'? Затем он войдет в первую часть 'ifence ... Я проверил исходный код AngularJS для' isObject', но я не уверен ... – LeoLozes