I believe the title is descriptive. The thing is:
I've got a parent component (shows the result), child1 (has checkboxes) and child2 nested in child1 (has input-text and buttons).
When I set the input in child2 via keyboard everything is fine, but when I use the buttons to change the value, its parent (child1 in this case) doesn't see it.
A bit of code here:
Parent.ts:
import { ProductService } from './../../services/product.service';
import { Product } from './../../interfaces/product';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
public products: Product[];
public basePrice: number; // representa los precios de los componentes de Home Component
public panelPrice!: number; // representa los precios de los componentes de WebPanel Component
public totalPrice: number; // representa la suma de base+panel
public isChecked: boolean;
constructor(private productService: ProductService) {
this.products = [];
this.totalPrice = 0;
this.basePrice = 0;
this.isChecked = false;
}
ngOnInit(): void {
this.getProducts();
}
getProducts(): void{
this.productService.getProducts()
.subscribe(p => this.products = p);
}
getPrice(p: Product){
p.isChecked ? this.basePrice+=p.price : this.basePrice-=p.price;
this.totalPrice = this.basePrice;
}
getName(p: Product){
return p.name;
}
getPanelPrice(evt: string){
this.panelPrice = Number(evt);
this.panelPrice === 30 ? this.panelPrice = 0 : this.panelPrice;
//condicional para controlar si el user introduce 1 página + 1 idioma: estaría dentro del precio base, con lo cual no hay que multiplicar nPages * nLang * 30
}
processTotalPrice(){
this.totalPrice = this.basePrice + Number(this.panelPrice);
// console.log('PanelPrice: ' +this.panelPrice);
}
}
Parent.html:
<h2>¿Qué quieres hacer?</h2>
<div class="container-check">
<div *ngFor="let p of products">
<app-my-checkbox [product]="p" (change)="getPrice(p)"></app-my-checkbox>
<div *ngIf="p.isChecked && p.name === 'web'">
<app-web-panel (emitterPanel)="getPanelPrice($event)" (change)="processTotalPrice();"></app-web-panel>
</div>
</div>
</div>
<p>Precio: {{ totalPrice | currency}} </p>
Child1.ts:
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
@Component({
selector: 'app-web-panel',
templateUrl: './web-panel.component.html',
styleUrls: ['./web-panel.component.scss']
})
export class WebPanelComponent implements OnInit {
@Input() public inputLabel!: string;
@Output() emitterPanel: EventEmitter<string> = new EventEmitter();
public nPages = 1;
public nLang = 1;
public label = {
pages: "Número de páginas",
lang: "Número de idiomas",
}
constructor() {
}
ngOnInit(): void {
}
getNPages(evt: string){
this.nPages = Number(evt);
console.log("Panel:// NPages: " + this.nPages)
}
getNLanguages(evt: string){
this.nLang = Number(evt);
console.log("Panel:// NLang: " + this.nLang)
}
calcPanelPrice(): string {
let result = this.nPages * this.nLang * 30;
return String(result);
}
emitOnChanges() {
console.log("Panel emitter:// Result: " + this.calcPanelPrice());
this.emitterPanel.emit(this.calcPanelPrice());
}
}
Child1.html:
<div class="panel">
<app-my-input-w-buttons [inputLabel]="label.pages" (emitterInputWButtons)="getNPages($event)" (change)="emitOnChanges()"></app-my-input-w-buttons>
<app-my-input-w-buttons [inputLabel]="label.lang" (emitterInputWButtons)="getNLanguages($event)" (change)="emitOnChanges()"></app-my-input-w-buttons>
</div>
Child2.ts:
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-my-input-w-buttons',
templateUrl: './my-input-w-buttons.component.html',
styleUrls: ['./my-input-w-buttons.component.scss']
})
export class MyInputWButtonsComponent implements OnInit {
@Input() public inputLabel: any;
@Output() emitterInputWButtons = new EventEmitter<string>();
public value:number = 1;
constructor() { }
ngOnInit(): void {
}
emitValue(){
this.emitterInputWButtons.emit(String(this.value));
}
increaseValue(){
this.value++;
this.emitValue();
}
decreaseValue(){
this.value === 1 ? this.value : this.value--;
this.emitValue();
}
}
Child2.html:
<div class="input-w-buttons">
<label for="input">{{inputLabel}}</label>
<button (click)="decreaseValue()">-</button>
<input [(ngModel)]="value" type="text" name="input" value="{{value}}" (change)="emitValue()" />
<button (click)="increaseValue()">+</button>
</div>