Декоратор Angular2 для двухсторонней привязки свойств

Из сообщения Виктора Савкина на синтаксис шаблона Angular2 показано, как использовать ввод и привязка выходного свойства -

<todo-cmp [model]="todo" (complete)="onCompletingTodo(todo)"></todo-cmp>

@Component({selector: 'todo-cmp'})
class TodoCmp {
  @Input() model;
  @Output() complete = new EventEmitter(); // TypeScript supports initializing fields
}

Свойство input украшено @Input (), а свойство output - @Output (). Как мне объявить свойство, которое будет иметь двустороннюю привязку свойств? Пример: Предположим, что компонент rootpanel имеет свойство «предложения» (типа string), а searchPanel имеет свойство «getSuggestions». Теперь я хочу, чтобы два свойства были связаны друг с другом в обе стороны. Я пытался -

rootpanel.html:

<search-panel [(getSuggestions)]="suggestions"> </search-panel>

Но я застрял при объявлении свойства getSuggestions в компоненте searchPanel. Каким должен быть тип свойства getSuggestions - string or EventEmitter<string>?

Пожалуйста, предложите.


person tyrion    schedule 15.01.2016    source источник


Ответы (3)


Если вам нужна двусторонняя привязка модели к родительскому компоненту:

[(model)]

В дочернем компоненте вам потребуется следующее:

@Input() model: string;
@Output() modelChange:EventEmitter<string>;

В какой-то момент, когда модель будет перезаписана в вашем дочернем компоненте, вы испустите событие modelChange:

updateModel(newValue:string) {
    this.model = newValue;
    this.modelChange.emit(this.model);
}

С точки зрения родительского компонента [(model)] эквивалентно:

[model]="model"  (modelChange)="model=$event"

Таким образом, когда свойство модели изменяется внутри дочернего компонента, изменение в модели распространяется вверх через двустороннюю привязку, синхронизируя все связанные модели на этом пути.

person pixelbits    schedule 15.01.2016
comment
Спасибо за объяснение. - person tyrion; 15.01.2016

Если вы хотите использовать стиль [(getSuggestions)] для двусторонней привязки, объявите поля, например

class TodoCmp {
  @Input() getSuggestions;
  @Output() getSuggestionsChange = new EventEmitter(); 

  onClick() {
    getSuggestions = 'someValue';
    getSuggestionsChange.emit(getSuggestions);
  }
}

getSuggestions, вероятно, не лучший выбор для такой комбинации ввода / вывода, но он должен продемонстрировать, как они связаны. Выход должен иметь то же имя, что и вход, с дополнительным Change. Если эта схема именования не подходит, используйте свой компонент, например

<search-panel [suggestions]="suggestions" (getSuggestions)="updateSuggestions($event)> </search-panel>

с вводом / выводом как

class TodoCmp {
  @Input() suggestions;
  @Output() getSuggestions = new EventEmitter(); 

  onClick() {
    suggestions = 'someValue';
    getSuggestions.emit(getSuggestions);
  }
}
person Günter Zöchbauer    schedule 15.01.2016
comment
Спасибо, это помогло. - person tyrion; 15.01.2016

Рекомендуемый подход к пиксельным битам - это именно то, как вы должны это делать, но если у вас есть несколько свойств двусторонней привязки данных в компоненте или даже тот, который часто изменяется в вашей кодовой базе, я создал для этого декоратор. Если вы используете npm, вот здесь. Просто зайдите на страницу gihub, если вам нужен код.

При этом вы можете напрямую использовать:

import { Component } from '@angular/core';
import { TwoWay } from 'two-way-decorator';
 
@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.scss']
})
export class ExampleComponent {
 
  @TwoWay()
  public text: string;
 
  @TwoWay()
  public count: number;
 
}

person Uifalean Sergiu Mihai    schedule 28.02.2020