0

我有一个包含两个嵌套组件的主组件,其中一个组件包含输入字段(2)和一个添加项目的按钮,另一个兄弟组件在循环中显示项目。

我有一个服务,它从输入组件中选择值并在服务本身中更新它的数组。

每当我填写输入并提交服务时,都会将新项目添加到数组中,但我需要更新需要显示此列表的兄弟组件。

我知道我必须从服务中获取值,因为它有一个更新的数组。

我不知道我可以在列表兄弟组件中使用哪个生命周期钩子来获取新列表,因为单击添加按钮时似乎没有调用 ngOnInit。

我不想使用事件发射器。

父组件

export class ShoppingComponent implements OnInit {
  ingredients:Ingredient[];

  constructor(private shoppingListService: ShoppingListService) { }

  ngOnInit() {
    this.ingredients = this.shoppingListService.getIngredients();
  }

} 

父 html

<div class="row">
    <div class="col-md-10">
        <app-shoppinglistedit></app-shoppinglistedit>
        <hr>
        <app-shoppinglist></app-shoppinglist>
    </div>
</div>

两个子组件放在父组件中:

列出兄弟姐妹

export class ShoppinglistComponent implements OnInit {
  ingredients: Ingredient[];

  constructor(private shoppingListService: ShoppingListService) { }

  ngOnInit() {
    this.ingredients = this.shoppingListService.getIngredients();
    this.oldLength = this.ingredients.length;
  }

}

它是 html/模板

<ul class="list-group">
    <a class="list-group-item" *ngFor="let ingridient of ingredients" >
        {{ ingridient.name }} <span class="badge badge-success badge-pill ml-auto">{{ ingridient.amount }}</span>
    </a>
</ul>

添加兄弟姐妹

export class ShoppinglisteditComponent implements OnInit {
  @ViewChild('nameRef', {static: true}) itemName:ElementRef;
  @ViewChild('amountRef', {static: true}) itemAmount:ElementRef;

  constructor(private shoppingListService: ShoppingListService) { }

  ngOnInit() {
  }

  onAddNewItem(){
    const name = this.itemName.nativeElement.value;
    const amount = +this.itemAmount.nativeElement.value;
    const ingredient = new Ingredient(name, amount);

    this.shoppingListService.addIngredient(ingredient);
    console.log("All ingredients: ");
    console.log(this.shoppingListService.getIngredients());

  }
}

它是模板 - html

<div class="row col-sm-12">
    <form>
        <div class="row">
            <div class="form-group col-sm-5">
                <label for="name">Name</label>
                <input id="name" class="form-control" type="text" name="name" #nameRef>
            </div>
            <div class="form-group col-sm-2">
                <label for="amount">Amount</label>
                <input id="amount" class="form-control" type="number" name="amount" #amountRef>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <button class="btn btn-success mr-2" type="button" (click)="onAddNewItem()">
                    <i class="fas fa-plus-circle"></i>&nbsp;Add Item
                </button>
                <button class="btn btn-danger mx-2" type="button">
                    <i class="far fa-trash-alt" (click)="onDeleteIngredient()"></i>&nbsp;Delete Item
                </button>
                <button class="btn btn-primary mx-2" type="button">
                    <i class="fas fa-adjust" (click)="onClearItem()"></i>&nbsp;Clear Item
                </button>
            </div>
        </div>
    </form>
</div>

4

1 回答 1

2

不使用 EventEmitter 会很棘手,CPU 资源消耗且无反应。让我向你提出一些建议:

@Input() ingredients: Ingredient[]首先为您的组件创建一个ShoppinglistComponent。您已经在父组件中获取了成分,因此您可以将它们传递给任何子组件(在我们的例子中为 ShoppinglistComponent)然后添加一个到您将在onAddNewItem方法中触发@Output() ingredientAdded = new EventEmitter()的组件ShoppinglisteditComponent 。在您的ShoppinglistComponent中收听输出(ingredientAdded)="insertNewIngredient($event)"

insertNewIngredient(addedIngredient: Ingredient): void {
  this.ingredients = this.ingredients.concat(addedIngredient)
}

当您使用输入将您的成分传递给您的ShoppinglistComponent时,它会自动更新您的视图。不需要生命周期钩子,只需使用一些公平的反应代码。

PS:

您确实应该在ShoppinglisteditComponent中使用反应式表单或模板驱动表单,因为您想管理表单,而 Angular 做得非常好(不要重新发明轮子)。这是一些使用 Reactive 表单的代码(不要忘记包括FormsModuleReactiveFormsModule

  form: FormGroup;

  constructor(
    fb: FormBuilder,
    private shoppingListService: ShoppingListService
  ) {
    this.form = fb.group({
      name: ['', Validator.required],
      amount: [0, [Validator.required, Validator.min(0)]]
    })
  }

  onAddNewItem(){
    const { name, amount } = this.form.value;
    const ingredient = new Ingredient(name, amount);
    this.shoppingListService.addIngredient(ingredient);
    console.log("All ingredients: ");
    console.log(this.shoppingListService.getIngredients());
  }
<div class="row col-sm-12">
    <form [formGroup]="form" (ngSubmit)="onAddNewItem()">
        <div class="row">
            <div class="form-group col-sm-5">
                <label for="name">Name</label>
                <input formControlName="name" id="name" class="form-control" type="text" required>
            </div>
            <div class="form-group col-sm-2">
                <label for="amount">Amount</label>
                <input formControlName="amount" id="amount" class="form-control" type="number" required>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <button class="btn btn-success mr-2">
                    <i class="fas fa-plus-circle"></i>&nbsp;Add Item
                </button>
                <button class="btn btn-danger mx-2" type="button">
                    <i class="far fa-trash-alt" (click)="onDeleteIngredient()"></i>&nbsp;Delete Item
                </button>
                <button class="btn btn-primary mx-2" type="button">
                    <i class="fas fa-adjust" (click)="onClearItem()"></i>&nbsp;Clear Item
                </button>
            </div>
        </div>
    </form>
</div>
于 2020-01-09T09:08:01.153 回答