Angular 2의 자식 구성 요소에서 부모 구성 요소 속성 업데이트


80

@input하위 구성 요소의 요소 중 하나에서 CSS 클래스를 활성화하기 위해 부모 구성 요소에서 속성을받는 데 사용 하고 있습니다.

부모로부터 속성을 받고 클래스를 활성화 할 수 있습니다. 그러나 이것은 한 번만 작동합니다. 부모로부터받는 속성은 부울 데이터 형식이며 false자식 구성 요소에서 상태를 설정하면 부모에서 변경되지 않습니다.

플 런커 : https://plnkr.co/edit/58xuZ1uzvToPhPtOING2?p=preview

app.ts

import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { HeaderComponent } from './header';
import { SearchComponent } from './header/search';

@Component({
  selector: 'my-app',
  template: `
    <app-header></app-header>
  `,
})
export class App {
  name:string;
  constructor() {
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, HeaderComponent, SearchComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

header.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-header',
  template: `<header>
              <app-search [getSearchStatus]="isSearchActive"></app-search>
              <button (click)="handleSearch()">Open Search</button>
            </header>`
})
export class HeaderComponent implements OnInit {
  isSearchActive = false;

  handleSearch() {
    this.isSearchActive = true
    console.log(this.isSearchActive)
  }

  constructor() { }
  ngOnInit() { }
}

header / search.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-search',
  template: `<div id="search" [class.toggled]="getSearchStatus">
              search 
              <button  (click)="getSearchStatus = false" class="close">Close Search</button>
            </div>`
})
export class SearchComponent implements OnInit {
  @Input() getSearchStatus: boolean;

  constructor() { }

  ngOnInit() {

  }
}

위에 주어진 플 런커를 확인하십시오. 열린 검색 기능은 한 번만 작동합니다. 검색을 닫은 후 다시 트리거되지 않습니다.

@input이 시나리오에 대한 적절한 사용 사례는 무엇입니까? 이 문제를 해결하도록 도와주세요. (플 런커를 업데이트하십시오).


`this.isSearchActive = false;`가 truein 으로 설정된 후 어디에 설정 handleSearch()합니까?
Günter Zöchbauer

in header / search.ts '<button (click) = "getSearchStatus = false"class = "close">'
본문

답변:


137

양방향 데이터 바인딩을 사용해야합니다.

@Input()단방향 데이터 바인딩입니다. 양방향 데이터 바인딩을 사용하려면 @Output()"변경"접미사와 함께 속성에 해당하는 항목을 추가해야합니다.

@Input() getSearchStatus: boolean;
@Output() getSearchStatusChange = new EventEmitter<boolean>();

귀하의 자산에 대한 변경 사항을 부모에게 게시하려면 부모에게 다음과 같이 알려야합니다.

this.getSearchStatusChange.emit(newValue)

부모에서 해당 속성에 대해 banana-in-a-box 표기법을 사용해야합니다.

[(getSearchStatus)]="myBoundProperty"

속성에 바인딩하고 자식에서 변경 될 때 콜백을 트리거 할 수도 있습니다.

[getSearchStatus]="myBoundProperty" (getSearchStatusChange)="myCrazyCallback($event)"

plnkr 참조


당신의 답변에 감사드립니다. 내 플 런커를 업데이트 해 주시겠습니까?
Body

1
을 사용하는 것과 동일한 동작에 대한 추가 작업이 추가됩니다 @Output(). 그것은 바퀴를 재조사하는 것처럼 들립니다. @RobertVangor
n00dl3

2
ReactiveForms를 사용할 때 내 자식 속성이으로 표시된 public경우에도 "banana box"접근 방식을 사용할 수 없으며 구성 요소의 알려진 속성이 아니라는 오류가 발생했습니다.에 바인딩 만 (propertyChanged)="setParentProp($event)"완벽하게 작동했습니다.
mc01

1
자체 게시물을받을 자격이 있기 때문에 귀하의 질문에 답변 할 수 없습니다. 문제는 부모의 변경 감지주기 직후에 변경 사항을 방출한다는 것입니다. 즉, Angular에서 허용하지 않는 일부 변경을 트리거하기 위해 변경 감지를 수행했습니다. @manoj
n00dl3

2
@Chandrakant 아니요, 바나나 상자 구문을 사용하려면 접미사 변경을 사용해야합니다. 사용자 지정 출력의 경우 원하는 이름을 지정할 수 있습니다. 바나나 상자는 많은 사람들이 오용 그냥 아주 바보 같은 구문 설탕입니다
Allwe

7

또 다른 접근 방식 : rxjs / BehaviorSubject를 사용하여 서로 다른 구성 요소간에 상태를 전달합니다.
여기에 plunkr가 있습니다.
접미사 'Rxx'로 제목을 지정하므로 searchStatus의 BehaviorSubject는 searchStatusRxx가됩니다.

  1. 같은 부모 구성 요소에서 초기화하십시오 searchStatusRxx = new BehaviorSubject(false);.
  2. @Input을 사용하여 자식 구성 요소에 전달하십시오.
  3. 자식 템플릿에서 비동기 파이프를 수행합니다.
  4. 부모와 자식 모두 searchStatusRxx.next(value)에서 최신 값을 변경해야합니다.

4

코드를 약간 편집하면 작동하고 더 간단하게 보입니다. 당신이 그것을 좋아한다면 말해.

https://plnkr.co/edit/oJOjEZfAfx8iKZmzB3NY?p=preview


감사합니다. 검색 구성 요소에서 상위 속성을 업데이트하고 싶습니다. 그것이 제 사용 사례입니다.
Body

@Body Fine,하지만 n00dl3 솔루션과 함께 버튼 및 클릭 메커니즘을 수정 한 방식을 사용하는 것을 고려해야합니다.
친절한 사용자

2

또 다른 방법. 플 런커 . 우리가 원하는 것은 진실의 단일 소스입니다. 이번에는 아이에게 넣을 수 있습니다.

  • 자식 초기화 : searchStatus = false
  • 부모 템플릿에서 자식의 인스턴스를 #as또는 다른 이름 으로 가져옵니다 .
  • 부모에서 #as.searchStatus및 자식을 사용하여 searchStatus를 변경합니다 this.searchStatus.

이 방법은 훨씬 더 좋고 간단합니다. 진행하는 데 유효한 방법입니까? Angular가이 방법을 홍보하지 않는 이유는 무엇입니까? 나는 일주일 이후로 해결책을 찾고 있으며 모든 곳에서 입출력 사례를 찾았습니다.
Body

이것을 "템플릿 참조 변수"방식이라고합시다. 간단 해 보입니다. 그러나 테스트하기가 조금 더 어려울 수 있으며 부모 / 자식 구성 요소가 함께 결합되어 좋지 않을 수 있습니다. 개인적으로 저는 BehaviorSubject 방식을 선호하는데, 이는 테스트 및 분리가 더 쉽고 부모와 자식 사이를 통과하는 복잡한 개체의 속성으로 설정할 수 있습니다. 참고 : Angular의 eventEmitter는 배후의 주제입니다.
Timathon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.