ng-model, ng-repeat 및 입력의 어려움


116

사용자가 ngRepeat및 을 사용하여 항목 목록을 편집 할 수 있도록하려고합니다 ngModel. ( 이 바이올린을 참조하십시오 .) 그러나 내가 시도한 두 가지 접근 방식 모두 기괴한 동작을 유발합니다. 하나는 모델을 업데이트하지 않고 다른 하나는 각 키 다운에서 양식을 흐리게합니다.

내가 여기서 뭔가 잘못하고 있니? 지원되는 사용 사례가 아닙니까?

다음은 편의를 위해 복사 한 바이올린의 코드입니다.

<html ng-app>
    <head>
        <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/css/bootstrap-combined.min.css" rel="stylesheet">
    </head>
    <body ng-init="names = ['Sam', 'Harry', 'Sally']">
        <h1>Fun with Fields and ngModel</h1>
        <p>names: {{names}}</p>
        <h3>Binding to each element directly:</h3>
        <div ng-repeat="name in names">
            Value: {{name}}
            <input ng-model="name">                         
        </div>
        <p class="muted">The binding does not appear to be working: the value in the model is not changed.</p>
        <h3>Indexing into the array:</h3>
        <div ng-repeat="name in names">
            Value: {{names[$index]}}
            <input ng-model="names[$index]">                         
        </div>
        <p class="muted">Type one character, and the input field loses focus. However, the binding appears to be working correctly.</p>
    </body>
</html>


1
이것은 stackoverflow.com/questions/12977894/… 와 매우 유사 하지만 두 번째 접근 방식은 여기에 새로 추가되었으므로 정확히 중복되는 것은 아닙니다. 나는 거기에 ng-repeat 자식 범위가 작동하는 방식을 설명하는 자세한 답변 (Artem의 것과 유사)을 제공했습니다.
Mark Rajcok 2012

이 스레드를 찾기 전에 적절한 인터넷 검색 비용이 들기 때문에 "ngRepeat 입력에서 업데이트되지 않은 상위 ​​모델"또는 "ngRepeat를 사용할 때 업데이트되지 않은 모델"또는 "(부모)에 바인딩되지 않은 ngRepeat 입력이 업데이트되지 않았습니다."와 같이 이름을 sth로 바꿀 수 있습니다. 모델"? 제목에 대한 더 나은 아이디어가 있습니까?
vucalur 2013 년

답변:


120

이것은 구속력이있는 문제인 것 같습니다.

조언은 프리미티브에 묶이지 않는다는 것 입니다.

귀하는 ngRepeat이 객체를 통해 반복하는을해야 할 때, 집합의 내부 문자열을 반복한다. 문제를 해결하려면

<body ng-init="models = [{name:'Sam'},{name:'Harry'},{name:'Sally'}]">
    <h1>Fun with Fields and ngModel</h1>
    <p>names: {{models}}</p>
    <h3>Binding to each element directly:</h3>
    <div ng-repeat="model in models">
        Value: {{model.name}}
        <input ng-model="model.name">                         
    </div>

jsfiddle : http://jsfiddle.net/jaimem/rnw3u/5/


3
흐림 / 초점 / 깜박임 문제를 설명하는 첫 번째 하이퍼 링크에 감사드립니다. 왜 그런 일이 일어 났는지 항상 궁금했습니다.
Mark Rajcok 2012

2
감사합니다. 그럼에도 불구하고, 프리미티브에 바인딩 ... IMO가 있어야한다
다니엘 Gruszczyk

1
이전 게시물하지만 thnx는 문제 'ngRepeat 내부 모델 변경하지 않는'를 찾기 위해 좀 시간이 걸렸습니다 그리고 프리미티브에 바인딩하지 조언했다
스테파노 CHRS에게

또한 입력하는 동안 전체 목록 을 수정하지 마십시오 . 내가 빠진 함정입니다. 컬렉션에서 변경 사항을 확인하고 동일한 복사본으로 교체했습니다. 따라서 기본 요소에 바인딩하지 않더라도 요소가 다시 생성되었습니다.
z0r

71

Angular 최신 버전 (1.2.1)을 사용하고 $index. 이 문제는 해결되었습니다.

http://jsfiddle.net/rnw3u/53/

<div ng-repeat="(i, name) in names track by $index">
    Value: {{name}}
    <input ng-model="names[i]">                         
</div>

일을했다; 더 이상 참조 손실
댄 Ochiana

너무 오래 검색 했어 .... 너무 쉬웠 어 ... 너무 숨겨져있어. 답으로 줘!
Andrea

oooooh, 그래서 ng-repeat에 "track by $ index"를 추가하면 "깜박임"문제도 해결됩니다
boi_echos

43

이 방법을 이해하는 것이 필요하다 때 어려운 상황에 들어가 범위 , ngRepeatngModelNgModelController의 일을. 또한 1.0.3 버전을 사용하십시오. 귀하의 예는 약간 다르게 작동합니다.

jm-에서 제공하는 솔루션을 간단히 사용할 수 있습니다.

그러나 상황을 더 깊이 다루고 싶다면 다음을 이해해야합니다.

  • AngularJS가 작동하는 방법 ;
  • 범위에는 계층 구조가 있습니다.
  • ngRepeat는 모든 요소에 대해 새로운 범위를 만듭니다.
  • 추가 정보 (hashKey)가있는 항목의 ngRepeat 빌드 캐시 캐시에없는 모든 새 항목에 대한 각 감시 호출에서 ngRepeat는 새 범위, DOM 요소 등을 구성 합니다. 자세한 설명 .
  • 1.0.3부터 ngModelController는 실제 모델 값으로 입력을 다시 렌더링합니다.

AngularJS 1.0.3에서 "각 요소에 직접 바인딩"예제가 작동하는 방식 :

  • 입력에 문자 'f'를 입력합니다.
  • ngModelController상품 범주 모델을 변경 (이름 배열이 변경되지 않는다) => name == 'Samf', names == ['Sam', 'Harry', 'Sally'];
  • $digest 루프가 시작됩니다.
  • ngRepeat항목 범위 ( 'Samf')의 모델 값을 변경되지 않은 이름 배열 ( 'Sam')의 값으로 대체합니다 .
  • ngModelController실제 모델 값 ( 'Sam')으로 입력을 다시 렌더링합니다 .

"배열로 인덱싱"예제의 작동 방식 :

  • 입력에 문자 'f'를 입력합니다.
  • ngModelController이름 변경 항목 array=>`names == [ 'Samf', 'Harry', 'Sally'];
  • $ digest 루프가 시작되었습니다.
  • ngRepeat'Samf'캐시에서 찾을 수 없습니다 .
  • ngRepeat 새 범위를 만들고 새 입력으로 새 div 요소를 추가합니다 (이것이 입력 필드가 포커스를 잃는 이유입니다. 이전 입력이있는 이전 div가 새 입력이있는 새 div로 대체 됨).
  • 새 DOM 요소에 대한 새 값이 렌더링됩니다.

또한 AngularJS Batarang 을 사용 하고 입력 한 입력으로 div 범위의 $ id가 어떻게 변경되는지 확인할 수 있습니다.


1.0.3 설명에 감사드립니다. 1.0.3에서 "직접 바인딩"의 경우 입력 필드가 변경 / 입력 된 입력을 받아들이지 않는 것처럼 보인다는 점에서 (적어도 Chrome에서는) 입력 필드가 깨진 것처럼 보입니다. 나는 가까운 장래에 이것에 대한 SO 게시물을 꽤 많이 보게 될 것이라고 확신합니다. :) 뭔가 잘못되었다는 것이 더 분명 할 것이기 때문에이 새로운 방법이 더 낫다고 생각합니다.
Mark Rajcok 2012

6

키를 누를 때마다 모델을 업데이트 할 필요가없는 경우에는 nameblur 이벤트에서 배열 항목에 바인딩 한 다음 업데이트 하기 만하면됩니다 .

<div ng-repeat="name in names">
    Value: {{name}}
    <input ng-model="name" ng-blur="names[$index] = name" />
</div>

사용하지 않는 이유는 ng-model="names[$index]"... 나는 그것을 해결 알고 있지만 ;-) 작동
Draško Kokić


2

문제 는 객체 ng-model와 함께 작동 input하고 덮어 쓰는 방식 name에있어 ng-repeat.

해결 방법으로 다음 코드를 사용할 수 있습니다.

<div ng-repeat="name in names">
    Value: {{name}}
    <input ng-model="names[$index]">                         
</div>

도움이되기를 바랍니다.


1

나는 그것이 매력처럼 작동한다는 내 문제에 대해 위의 해결책을 시도했습니다. 감사!

http://jsfiddle.net/leighboone/wn9Ym/7/

내 버전은 다음과 같습니다.

var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
    $scope.models = [{
        name: 'Device1',
        checked: true
    }, {
        name: 'Device1',
        checked: true
    }, {
        name: 'Device1',
        checked: true
    }];

}

및 내 HTML

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
         <h1>Fun with Fields and ngModel</h1>
        <p>names: {{models}}</p>
        <table class="table table-striped">
            <thead>
                <tr>
                    <th></th>
                    <th>Feature 1</td>
                    <th>Feature 2</th>
                    <th>Feature 3</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Device</td>
                   <td ng-repeat="modelCheck in models" class=""> <span>
                                    {{modelCheck.checked}}
                                </span>

                    </td>
                </tr>
                <tr>
                    <td>
                        <label class="control-label">Which devices?</label>
                    </td>
                    <td ng-repeat="model in models">{{model.name}}
                        <input type="checkbox" class="checkbox inline" ng-model="model.checked" />
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

-5

다음과 같이하는 방법 :

<select ng-model="myModel($index+1)">

그리고 내 관리자 요소에는 다음이 있습니다.

<select ng-model="myModel1">
...
<select ng-model="myModel2">
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.