Найти поле по его угловой модели

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

Например, есть input ng-model=users[2].name, я хочу, чтобы метод принимал строку "users[2].name" и возвращал элемент DOM.

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

Я могу сделать это с помощью jquery, но это довольно громоздко, так как это вряд ли так просто, как input[ng-model="user[0].name"] селектора input[ng-model="user[0].name"]. Он обычно похож на ng-repeat="user in users" и на несколько уровней. Или, что еще хуже, в смеси ng-repeat-start и ng-repeat-end.

Решение, изменяющее users[2].name а затем поиск измененных элементов DOM, вероятно, тоже будет в порядке.

Я создал плунж, надеюсь, показывая то, что хотел.

3 ответа

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

<blockquote>

Предостережение: <span>это работает, если ваше выражение модели ng имеет точку, иначе прототипная цепочка наследования не существует для распространения временного изменения.</span>

>> Плунж

обзор

Во-первых, мы украшаем директиву ng-model, чтобы отслеживать всю ng-model в приложении. Эти модели хранятся в массиве myModels. Затем мы просматриваем myModels ищем все модели, которые оценивают ценность, которую мы ищем, и вставляем их в массив possibleMatches массивов. Наконец, мы изменяем целевое значение и цикл через possibleMatches, чтобы определить, какой из них на самом деле изменилось.

Код:

angular.module('find_by_model', [])

.constant('myModels', [])

.config(function($provide, myModels) {
 window.myModels = myModels; // just for debugging

 $provide.decorator('ngModelDirective', function($delegate) {

 var directive = $delegate[0];

 var compile = directive.compile;

 directive.compile = function(tElement, tAttrs) {
 var link = compile.apply(this, arguments);
 tElement.append('<div>Added in the decorator</div>');
 return function(scope, elem, attrs) {
 link.apply(this, arguments);
 v = scope.$eval(tAttrs.ngModel);
 myModels.push({scope: scope, elem:elem,
 val: function() {
 return scope.$eval(tAttrs.ngModel);
 },
 }); 
 }; 
 };

 return $delegate;
 });
})

.factory('finder', function (myModels) {
 function findElem($scope, path) {
 var originalVal = $scope.$eval(path),
 possibleMatches = [],
 result = null;

 angular.forEach(myModels, function (model) {
 if (angular.equals(model.val(), originalVal)) possibleMatches.push(model);
 });

 // temp change: the blah property is arbitrary
 try {
 var newVal = $scope.$eval(path + " = " + JSON.stringify({ val: path, blah: 'changed'}) );
 } catch(e) {
 return null;
 } 

 // find it: note: this could be made more efficient with a breaking loop
 angular.forEach(possibleMatches, function (model) {
 if (angular.equals(model.val(),newVal)) result = model;
 });

 // reset
 $scope.$eval(path + " = " + JSON.stringify(originalVal));

 return result && result.elem;
 }

 return {
 findElem: findElem
 }
})

И вот как вы его используете (предполагая, что вы уже ввели finder):

$scope.expressionToFind = "m.top[0].name";

 var el = finder.findElem($scope, $scope.expressionToFind);
 if (el) 
 angular.element(el).css('outline', '1px solid red');
 else
 alert('not found');


Примечание: maaartinus попросил ООН -deleted этот ответ, но это не так

Здесь ответ написан в комбинации psuedo-кода и JavaScript...

function findElem() {
 var originalVal = users[2].name
 var possibleMatches = []

 for each elem in the page:
 ngElem = angular.element(elem);

 var id = 0
 for each watcher in ngElem.scope().$$watchers
 if (watcher.last === originalVal) {
 possibleMatches.push({ngElem: ngElem, watcherId: id})
 }
 id++

 var changedVal = users[2].name = users[2].name + 'changed'
 $scope.$apply()

 for each possibleMatch in possibleMatches
 var s = possibleMatch.ngElem.scope()
 var mid = possibleMatch.watcherId
 if (s.$$watchers[mid].last == changedVal)
 return ngElem; // found

 return null; // not found
}


Вот простой пример доступа к элементу внутри директивы:

http://plnkr.co/edit/2gU3d7UMYG1D7nWMjbvo?p=preview

Если по какой-то причине вы не можете изменить html, это способ, отличный от углового:

window.onload=function(){
 var ele=getElementsByModel(document,'name');
 for(var i=0;i

licensed under cc by-sa 3.0 with attribution.