2013-06-19 5 views
10

자세한 정보가 필요하거나 무엇인가를 명확히하기를 원한다면 알려주십시오. 나는 이것을 알아 내기 위해 많은 다른 것들을 시도했지만 해결책을 찾지 못했습니다.AngularJS 중첩 된 지시문에서 양방향 데이터 바인딩

저는 angularJS에 비교적 익숙하며 여러 계층의 데이터로 앱을 제작하려고합니다. 컨트롤러의 PageController에서 본체의 범위에 저장된 기본 사용자 정보가 있습니다. 그런 다음 템플릿 목적을위한 몇 가지 사용자 지정 지시문을 포함하는 $ routeParams (컨트롤러 SettingsController 사용)를 사용하여로드되는 설정 양식을 갖습니다. 지시문이 중첩되어 있으므로 첫 번째 부분의 두 번째 항목을로드하기 위해 transclusion을 사용하고 있습니다. 이 모든 것이 제대로 작동하는 것 같습니다.

내 문제는 내측 지시문 내에서 user.firstname 필드를 참조하려고하며 양방향 데이터 바인딩을 사용하여 텍스트 상자에 대한 변경을 허용하여 PageController 범위의 값도 변경되도록 허용하려고합니다. 나는 이런 종류의 문제들이 ng-model에서 primitives를 사용함으로써 야기된다는 것을 알고 있지만, 나는 여분의 객체 안에 모든 것을 넣으려고 시도했기 때문에 prototypal 상속을 사용할 수 없게 만들었습니다. 여기서 내가 뭘 잘못하고 있니?

내 코드는 JSFiddle이며 가능한 한 줄여서 문제를 해결합니다. 이 예에서는 PageController 범위에 직접있는 외부 텍스트 상자에 입력하면 해당 텍스트 상자가 수정 될 때까지 내부 텍스트 상자가 수정되어 연결이 끊어집니다. 이것은 다른 질문에 설명 된대로 프리미티브를 사용하는 문제와 같지만 문제가있는 곳을 파악할 수 없습니다.

HTML :

<body class="event-listing" ng-app="app" ng-controller="PageController"> 
    <div class="listing-event-wrap"> 
     <input type="text" ng-model="user.firstname" /> 
     <div ng-controller="SettingsController"> 
      <section block title="{{data.updateInfo.title}}" description="{{data.updateInfo.description}}"> 
       <div formrow label="{{data.updateInfo.labels.firstname}}" type="textInput" value="user.firstname"></div> 
      </section> 
     </div> 
    </div> 
</body> 

각도 지침 :

app.directive('formrow', function() { 
return { 
    scope: { 
      label: "@label", 
      type: "@type", 
      value: "=value" 
    }, 
    replace: true, 
    template: '<div class="form-row">' + 
      '<div class="form-label" data-ng-show="label">{{label}}</div>' + 
      '<div class="form-entry" ng-switch on="type">' + 
       '<input type="text" ng-model="value" data-ng-switch-when="textInput" />' + 
      '</div>' + 
     '</div>' 
} 
}); 
app.directive('block', function() { 
return { 
    scope: { 
      title: "@title", 
      description: "@description" 
    }, 
    transclude: true, 
    replace: true, 
    template: '<div class="page-block">' + 
      '<h2 data-ng-show="title">{{title}}</h2>' + 
      '<p class="form-description" data-ng-show="description">{{description}}</p>' + 
      '<div class="block-inside" data-ng-transclude></div>' + 
      '</div>' 
} 
}); 

각도 컨트롤러 :

app.controller("PageController", function($scope) { 
    $scope.user = { 
     firstname: "John" 
    }; 
}); 
app.controller("SettingsController", function($scope) { 
    $scope.data = { 
     updateInfo: { 
      title: "Update Your Information", 
      description: "A description here", 
      labels: { 
       firstname: "First Name" 
      } 
     } 
    } 
}); 

답변

9

난 너무 이전 코드를 찾아보십시오. 다음과 같이 대신 사용해보십시오 : http://jsfiddle.net/CxNc2/2/

실제 값을 전달하는 대신 객체와 올바른 값을 가리키는 포인터를 전달합니다. 여기 'refobject'덧붙여

<body class="event-listing" ng-app="app" ng-controller="PageController"> 
    <div class="listing-event-wrap"> 
     <input type="text" ng-model="user.firstname" /> 
     <div ng-controller="SettingsController"> 
      <section block title="{{data.updateInfo.title}}" description="{{data.updateInfo.description}}"> 
       <div formrow label="{{data.updateInfo.labels.firstname}}" type="textInput" refobj='user' value="firstname"></div> 
      </section> 
     </div> 
    </div> 
</body> 

및 여기 refobj + 부가가치 : ng-model="someobj.somevalue"보다 지향성의 텍스트 박스가 모델 대신 객체의 프리미티브를 사용하므로

app.directive('formrow', function() { 
    return { 
     scope: { 
      label: "@label", 
      type: "@type", 
      value: "@value", 
      refobj: "=" 
     }, 
     replace: true, 
     template: '<div class="form-row">' + 
      '<div class="form-label" data-ng-show="label">{{label}}</div>' + 
      '<div class="form-entry" ng-switch on="type">' + 
     '<input type="text" ng-model="refobj[value]" data-ng-switch-when="textInput" />' + 
      '</div>' + 
     '</div>' 
    } 
+0

빠른 응답을 보내 주셔서 감사합니다. 나는 바이올린을 시도했지만 그것은 내가 올린 것과 똑같은 것을하는 것처럼 보인다. 기능 분리 스코프로 변경하려는 목표는 무엇입니까? – princjef

+0

refobj를 추가 했으므로 지시어 내에서 'firstname'을 호출 할 필요가 없으므로 이것이 일반화되기를 바랍니다. – Nir

+0

정말 똑똑합니다! 점 대신 배열 표기법을 사용하는 것에 대해 생각하지 않았습니다. 이것은 나의 필요를 위해 작동 할 것이다. 감사! – princjef

8

(ng-model="value"을), 해당 모델은 로컬 범위에서만 생성되며 부모는 이에 액세스 할 수 없습니다.

<div formrow ... value="user"></div> 
:

ng-model="value.firstname" 

그럼 대신 프리미티브 속성의 지정에 전체 user 객체를 전달한다

수정 프로그램 객체 속성으로서 dot rule를 사용하여 지향성 텍스트 박스 모델을 정의하는 것이다

Here is a demo

+0

오, 어디서 잘못되었는지 알 수 있습니다. 통찰력을 주셔서 감사합니다. – princjef

+0

안녕하세요, 저는 물건을 더 명료하게 보려고 데모를 단순화했습니다. 복잡한 오브젝트에서는 작동하지만 간단한 속성에서는 작동하지 않습니다 ... [여기는 업데이트 된 버전입니다] (http://jsfiddle.net/BXRnM/4/). 왜 볼 수 있니? – Dmitry

+0

@Dmitry 간단한 속성에 대한 예제에서 OP의 오류가 다시 발생합니다.간단히 말하면, Angular scope inheritance _는 단순한 프리미티브 변수가 아니라 객체가 필요합니다. 이것은 자바 스크립트에서 프로토 타입 상속의 직접적인 결과입니다. [[이 답변] (http://stackoverflow.com/questions/16928341/update-parent-scope-variable/16929117#16929117)을 살펴볼 수 있습니다. 다른 예제를 보거나 [[this Q & A] (자세한 내용은 http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-protypical-inheritance-in-angularjs)]를 참조하십시오. – sh0ber

0

문제 i s의 원인은 ng-switch입니다. 문서 Understanding scope git에서 가져 왔습니다.

ng-switch 범위 상속은 ng-include와 동일하게 작동합니다. 따라서 부모 범위의 프리미티브에 양방향 데이터 바인딩이 필요하면 $ parent를 사용하거나 모델을 개체로 변경 한 다음 개체의 속성에 바인딩합니다. 이렇게하면 부모 범위 속성의 하위 범위 숨기기/섀도 잉이 수행되지 않습니다.

텍스트 상자에 텍스트를 입력하면 코드 아래 은 ng-switch 범위에서 실행됩니다.

$scope.value="the text you typed"

그래서 ng-switch 범위에 대한 새로운 속성을 생성합니다 value .this를 검색 할 프로토 타입 체인을 참조하지 않습니다.

증언하는 방법?

value$parent.value으로 변경하면 모든 것이 잘 작동합니다. 왜냐하면 ng-switch에서 원시 타입 (angularjs는 도트가없는 경우 value을 원시 타입으로 인식합니다) $parentformrow 지시어 범위를 나타냅니다.

ng-switch을 제거하려고하거나 의사의 지시에 따라 수행하십시오. 문제는 사라질 것입니다.

더 중요한 점은 양방향 바인딩을 적용 할 때 항상 .이라는 점을 사용하여 모델을 참조하는 것이 좋습니다.

내가 잘못 말하면. 제발 친절하게 나를 정정하고 바르게 만들어 줘.

관련 문제