Настройте двунаправленную привязку из объекта, определенного в атрибуте html в AngularJS.

Я реализовал директиву удаленной проверки, которая запрашивает указанную конечную точку JSON API после размытия ввода. Ожидается ответ { valid: true|false }.

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

Мое определение тега выглядит следующим образом:

<input remote-validate endpoint="/api/action/:value" ng-model="MyInput" />

где :value заменяется закодированным в urlencode значением $scope.MyInput. Это работает хорошо.

То, что мне нужно, это конечная точка, подобная этой /api/action/:value/:person/:thing, замены :person и :thing привязаны к значениям родительской области. Моя первоначальная мысль заключалась в том, чтобы иметь атрибут bindings, который сопоставляет родительскую область с конечной точкой.

<input remote-validate endpoint="/api/action/:value/:person/:thing" bindings="{person: 'firstName', thing: 'thingName'}" ng-model="MyInput" />
(...)
<input ng-model="firstName" />    <input ng-model="thingName" />

учитывая var bindings = scope.$eval(attrs.bindings);, есть ли способ пройти через объект bindings и создать двустороннюю привязку к родительской области?

РЕДАКТИРОВАТЬ: Обходной путь может заключаться в следующем:

<input validate-remotely 
    endpoint="api/action/:value/:param1/:param2" 
    param1="person" 
    param2="thing" />

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

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


person Stan Bondi    schedule 11.07.2013    source источник
comment
почему бы вам просто не использовать двунаправленную привязку, используя '=', доступную с директивами   -  person Ajay Beniwal    schedule 11.07.2013
comment
Потому что я хочу сопоставить произвольно названные :tags в строке конечной точки URL с родительской областью. Я знаю, что мог бы сделать что-то вроде этого: ‹input validate-remotely endpoint=:a/:b/:c a=parentModel ... /›, но тогда мне пришлось бы определить 'a' в моей директиве. scope: {a:'='} - что означало бы, что моя директива не является общей.   -  person Stan Bondi    schedule 11.07.2013


Ответы (2)


Как я узнал вчера, вы можете использовать $parse в своих атрибутах «привязки». см. этот пост. Это хороший способ $watch атрибута для изменений, исходящих от родительского или дочернего элементов.

Пример:

<div parse-test bindings="{person: 'firstName', thing: 'thingName'}"></div>

// in your directive link function:
scope.bindings = $parse(attrs.bindings)(scope);
  scope.$watch('bindings', function(val){
    for (i in scope.bindings){
      scope[i] = scope.bindings[i];
    }  
  }, true);

Поэкспериментируйте с этой планкой

person rGil    schedule 11.07.2013
comment
Спасибо за ваш ответ, это помогло мне найти решение :) - person Stan Bondi; 19.07.2013

Вот как я решил это не таким идеальным способом.

См. этот планкер, в котором есть копия директивы, которую я использую вживую, и которая хорошо работает в моем app, но не работает в Plunker (я ожидаю, что случайно выбранная конечная точка plunker API будет вызвана и завершится ошибкой, но она не вызывается из-за некоторых странных ошибок, которые я не хочу отлаживать).

Проблема, с которой я столкнулся с предложенным обходным путем в РЕДАКТИРОВКЕ этого вопроса, заключается в том, что вы не можете использовать scope и require в одном и том же directive. Я был бы рад, если бы кто-нибудь мог уточнить, так ли это и почему.

Обходной путь

Я использовал атрибут params, чтобы указать дополнительные данные в нотации объекта, которые должны быть расширены для перехода к запросу ресурсов. Я использовал синтаксис handlebars в атрибуте params для динамического изменения строки обозначения объекта.

<input ng-model="value2" ... />
<input validate-remotely 
       endpoint="/api/:value/?thing=:anotherValue" 
       params="{ anotherValue: '{{ value2 }}' }"  ... />

Не так здорово :/ но это работает.

Затем на blur проверенного ввода я переоцениваю строку объекта (app.js:40 в планкере) и расширяю данные ресурсов, чтобы включить этот объект, который с помощью нотации ngResources двоеточия (:) заменяет URL-адрес.

Проверка имеет 3 состояния:

remoteValidityPending: проверка поля не удалась, потому что оно все еще проверяется — подходит для отображения счетчика.

remoteValidityUnchecked: Поле изменилось с тех пор, как оно было проверено, но еще не размыто - гарантирует, что любые кнопки отправки `ng-disable="form.$invalid"' останутся отключенными, пока мы не узнаем, что серверная часть вернула ответ.

remoteValidity: Если это проходит успешно, была вызвана конечная точка поля, и с сервера было возвращено «{valid: true}».

Я почти уверен, что есть лучшие/другие способы решить эту проблему, и я буду рад изменить ответ, если кто-то улучшит эту директиву. Я надеюсь, что это поможет кому-то там.

person Stan Bondi    schedule 19.07.2013