2

特定の angularjs モデルに対応するフィールドをどうにかして見つけることはできますか? 1 つの変数に対応するフィールドが複数ある場合もあれば、まったくない場合もありますが、これは問題ではありません。

たとえば、文字列を取得して DOM 要素を返すinput ng-model=users[2].nameメソッドが必要です。"users[2].name"

ユーザー入力の一種のデモが必要なため、高速である必要はありません。たとえば、ユーザーが名前フィールドに入力する必要がある場合は、(マウスをシミュレートする) オーバーレイをそこに移動し、プログラムで入力します。シ

jquery を介して実行できますが、セレクターほど簡単ではないため、これはかなり面倒input[ng-model="user[0].name"]です。それは通常ng-repeat="user in users"、数レベルの深さに埋もれています。さらに悪いことに、 と が混在しng-repeat-startていng-repeat-endます。

ソリューションを変更users[2].nameしてから、変更された DOM 要素を見つけることもおそらく問題ありません。

うまくいけば、私が望んでいたものを示すプランクを作成しました。

4

3 に答える 3

1

元の回答とは異なり、実際に機能するため、この回答を追加しています。また、これはかなり異なるアプローチであるため、単にそれに追加したくありませんでした。

警告:これは、ng-model 式にドットがある場合に機能します。そうでない場合、一時的な変更を伝達するためのプロトタイプの継承チェーンが存在しません。

>>プランク

概要

まず、アプリ内の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');
于 2014-06-28T05:15:52.853 に答える
1

注: maaartinus からこの回答の削除を取り消すように依頼されましたが、それは間違っています


これは、疑似コードと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
}
于 2014-06-26T17:42:32.907 に答える