2016-10-30 2 views
13

이 질문의 맛은 출시하기 전에 Angular2의 다양한 버전에서 여러 번 묻습니다. 그러나, 나는 아직 여기에 큰소리로 원하는 행동 (부족한 해결 방법의 부족)을 생산할만한 것을 찾지 못했습니다. Select Object Problemsangular2 ngModel/ngValue 옵션 개체 - 다른 인스턴스에서 동일 함을 나타냅니다.

내 양식 선택은 [(ngModel)]을 (를) 통해 객체를 생성 한 다음 비슷한 객체 (모두 ID로 구별됨)의 목록을 보려면 * ngFor를 통해 'option'이 생성됩니다. 내 연구에서 Angular2가 (인스턴스에 의해) JavaScript 객체 등가성을 사용한다는 것을 여러 번 언급 했으므로 동일한 인스턴스가없는 바인딩 된 모델의 객체는 목록과 일치하지 않습니다. 따라서 "2-way"데이터 바인딩을 깨는 "선택된"항목으로 표시되지 않습니다.

그러나이 인스턴스가 일치하는 방법을 정의하고 싶습니다. 인터넷에서 떠 다니는 일부 솔루션이 시도되었지만 작은 조각이 누락되었거나 제대로 구현되지 않았습니다.

  • ngModel에서 개체 (즉 ID) 이외의 다른 바인딩 :

    옵션은 내가 피하려고. ngValue는 유용한 활용입니다.

  • 변경 핸들러를 통한 해결 방법
  • 인스턴스가 일치하도록합니다 (데이터 서비스에서 개체를 가져오고 있으며 모두 일치하도록 재정의하고 싶지는 않습니다 ...). 자원의 불필요한 낭비 같은)

이상적으로 (솔루션 - 내 솔루션이 부족한 솔루션이있는 곳에서 가능한 한 논의 된 것 같습니다.) ngModel에 대한 평등 표준을 정의 할 수 있습니다. 오브젝트 인스턴스 평등 대신에 사용하십시오.

즉, 아래의 최신 시도입니다. 여기서 h.id == a.id는 "selected"속성을 정의합니다. 왜 "selected"속성이 렌더링되지 않는지 이해할 수 없습니다. ngModel에 의해 어떻게 든 차단됩니까? HTML에서 selected = 'true'를 수동으로 설정하는 것은 수정하는 것처럼 보이지만 [attr.selected] 또는 ng-reflect-selected = 'true'속성을 만드는 다른 변형으로 생성하는 것은 트릭을 수행하지 않는 것 같습니다.

<div *ngFor='let a of activePerson.hobbyList ; let i=index; trackBy:a?.id'> 

    <label for='personHobbies'>Hobby:</label> 
    <select id='personHobbies' class='form-control' 
     name='personHobbies' [(ngModel)]='activePerson.hobbyList[i]' #name='ngModel'> 

     <option *ngFor='let h of hobbyListSelect; trackBy:h?.id' 
      [ngValue]='h' 
      [attr.selected]='h.id == a.id ? true : null' 
     > 
     {{h.name}} 
     </option> 
    </select> 
</div> 

어떤 것들은 내가 시도 :

  • trackBy을
  • [선택] = 선택은 = {{}}이, 그리고 [attr.selected (이 보인다 닫기)
  • 에 바인딩
I는 다음과 같습니다 렌더링 된 HTML 달성 성공적으로 한

:

<select ...> 
    <option selected='true'>Selected</option> 
    <option selected='false'>Not Selected</option> 
    <!-- and variants, excluding with selected=null--> 
</select> 
0123을

개체 인스턴스가 다른 경우에도 여전히 선택된 값이 없습니다. 나는 또한 사용자가 값을 선택할 때 HTML 또는 CSS의 어떤 요소가 선택된 값을 기록하는지 알아 내려고 시도했다. (ngModel이 처리하는 방법과 처리 할 수있는 다른 옵션이 무엇인지).

도움을 주시면 감사하겠습니다. 목표는 기본 모델을 변경하고 그에 따라 선택 상자를 업데이트하기 위해 "변경"단추를 얻는 것입니다. "hobbyList"에 대한 내 시도에 집중했습니다. Firefox와 Chrome에서 사용해 보았습니다. 감사!당신이 선택한 일을 할 곳에서 전달 된 객체를 얻을 때

+0

을, 나는 그 [이] (HTTP를 발견했습니다 : //stackoverflow.com/questions/37728121/angular2-select-initial-object-with-ngvalue)는 완전히 사실입니다. 그러나 ngValue를 사용하고 두 객체를 비교할 때 초기 선택 옵션을 설정하는 방법이 있어야합니다. – BuddhistBeast

+0

단순히 기존 배열 데이터를 업데이트하고 새 데이터를 만드는 대신 사용하십시오. 새로운 개체를 만들면 기존 기능을 손상시킬 수 있습니다. 거기에 아무런 문제가 없으며 문자열 기본 요소 대신 객체를 비교하고 있습니다 (예상 한대로). 원하는 것을 얻기 위해 프로토 타입을 수정해야하지만 올바른 방법은 모델 데이터를 업데이트하는 것입니다. 개체 대신 ID 번호 또는 문자열 배열을 사용할 수도 있으며 그렇게하면 잘 작동합니다. – Kesarion

+0

선택할 수있는 옵션의 배열은 객체 자체와 별도의 데이터 서비스에서 나옵니다. ngValue를 사용하여 프레임 워크와 일관된 방식으로 작업하고 싶지만 프레임 워크가 지원하지 않으면 명확하게 해결해야합니다. 솔직히 "selected"속성을 강요하면 원하는 동작이 제공되지 않습니다. 개발자 모드에서 "selected = true"를 입력하면 원하는대로 작동하지만 angular2를 통해 동일한 작업을 수행하지는 않습니다. 또한, angular2를 통해 시도하면 개발자 모드 편집이 작동하지 않습니다. – cole

답변

4

당 @Klinki

참조 현재 앵귤러 2에는 간단한 해결책이 없지만 앵글 4에서는 입니다. 베타 6 이후에는 이미-compareWith https://github.com/angular/angular/pull/13349

이 제안 된 경우에 사용 (see plunk) 설명을 참조하십시오 :이 현상금와 함께 제공되는 자원으로

<div *ngFor='let a of activePerson.hobbyList ; let i=index;'> 

     <label for='personHobbies'>Hobby:</label> 
     <select id='personHobbies' class='form-control' 
      name='personHobbies' [(ngModel)]='activePerson.hobbyList[i]' 
      [compareWith]='customCompareHobby'> 
      <option *ngFor='let h of hobbyListSelect;' [ngValue]='h'>{{h.name}}</option> 
     </select> 

</div> 
... 
customCompareHobby(o1: Hobby, o2: Hobby) { 
    return o1.id == o2.id; 
} 
-1

, 단지 일치하는 항목에 대한 hobbyListSelect 배열을 검색없이 바로 전달 방식 사용에있다 activePerson.hobbyList[i]

+1

그의 3 가지 제약 조건 세트는 재사용하기 때문에 좌절감을주는 정상적인 접근 방식을 없앱니다. 객체는 id에서 일치하는 것처럼 깔끔하게 해결하며 세 번째 가능한 솔루션이 있다고 생각합니다 (여러 가지 항목을 시도했지만 제약 조건을 충족시키지 않고 올바른 동작을 얻을 수는 없음). 대답은 "프레임 워크의 제약 조건 내에서 작동하도록 프로그램을 다시 디자인해야 할 때가 있습니다." – silentsod

+0

어떤 사람들은 객체가 작동하는 방식에 신경 쓰지 않고 모든 것이 마술처럼 작동하기를 원합니다. 이러한 기능이 구현 될 때마다 Angular2와 같은 프레임 워크를 없애기 때문에 불만을 없애기 위해 드문 경우에만 복잡하고 유지하기가 쉽습니다. 사용자의 ;-) 다트에서는'equals' 연산자를 오버라이드 할 수 있지만, 보통 언어는 아마도 여기에 요구되는 것이 아닐 것이라고 생각합니다. –

0

에 발견 된 항목을 할당 이 방법으로 ngModel 바인딩. 그러나 이벤트 처리기를 별도로 등록하지 않으므로 개체 할당 방법을 변경해야 할 수도 있습니다. select 태그에 id를 할당 할 필요가 없으므로 목적에 맞지 않습니다. 언급 된 유스 케이스의 경우 양방향 바인딩을 보도록 수정했습니다.

모델의 구성 요소 생성자를 찾아서 변경 사항을 테스트하기 위해 printVal()가 포함되어 있습니다. 템플릿에는 ngValue 및 ngModel이 포함되지 않지만 예상대로 작동 할 수 있습니다.

constructor() { 
 
    this.activePerson = {id: 'a1', 
 
     hobbyList : [ 
 
      { 
 
      id: 'h4' 
 
      }, 
 
      { 
 
      id : 'h2' 
 
      } 
 
      ] 
 
     } 
 
     
 
    this.hobbyListSelect = [ 
 
     { 
 
     id: 'h1' 
 
     }, 
 
     { 
 
     id : 'h2' 
 
     }, 
 
     { 
 
     id: 'h3' 
 
     }, 
 
     { 
 
     id : 'h4' 
 
     } 
 
     ]; 
 
    } 
 

 
printVal($event,i) { 
 
    console.log(JSON.stringify(this.activePerson.hobbyList)) 
 
}
<div *ngFor='let a of activePerson.hobbyList ; let i=index; trackBy:a?.id'> 
 
     <label for='personHobbies'>Hobby:</label> 
 
     <select name='personHobbies' 
 
     (change)=" activePerson.hobbyList[i] = hobbyListSelect[$event.target.selectedIndex]; 
 
     printVal($event,i)"> 
 
      <option *ngFor='let h of hobbyListSelect; trackBy:h?.id' 
 
       [selected]='(h.id == a.id) ? "selected" : null' 
 
      > 
 
      {{h.id}} 
 
      </option> 
 
     </select> 
 
    </div>

+0

'trackBy'가 올바르지 않습니다. 인수. 귀하의 경우'trackBy : a => a && a.id'. – kub1x

4

현재 각 2 간단한 해결책이 없지만, 각 사이 이미 베타 6 이후 해결되었습니다 - https://github.com/angular/angular/pull/13349

+1

이것은 선택된 대답이어야합니다 –

+1

나는이 답변에 매우 감사하고 있습니다 만, 링크가 없으면 많이 제공하지 않습니다. 질문에 대답하는 상황 별 응용 프로그램 – cole

관련 문제