#javascript #angular #primeng #angular-components
#javascript #angular #primeng #angular-components
Вопрос:
Я работаю над приложением Angular с использованием PrimeNG, и у меня следующая проблема.
У меня был компонент, содержащий диалог PrimeNG, определенный внутри (этот: https://www.primefaces.org/primeng/showcase/#/dialog ) и это прекрасно работает.
Чтобы сохранить аккуратный код, я решил его реорганизовать и создал подкомпонент, содержащий только диалоговое окно PrimeNG. Итак, в основном, теперь у меня есть что-то вроде этого:
РОДИТЕЛЬСКИЙ КОМПОНЕНТ HTML::
<app-employee-add-form [displayNewEmployeeDialog]="displayNewEmployeeDialog"></app-employee-add-form>
<div class="container">
<!-- TOOLBAR -->
<div class="card" id="toolbar-card">
<div class="toolbar-container">
<div class="row">
<div id="toolbar-left" class="col-6 d-flex justify-content-start">
<button pButton pRipple label="New" icon="pi pi-plus"
class="p-button-success p-mr-2"
(click)="showNewEmployeeDialog()">
</button>
<button pButton pRipple icon="pi pi-trash" class="p-button-danger"></button>
</div>
<div id="toolbar-right" class="col-6 d-flex justify-content-end">
<!--<p-fileUpload mode="basic" accept="image/*" [maxFileSize]="1000000" label="Import" chooseLabel="Import" class="p-mr-2 p-d-inline-block"></p-fileUpload>-->
<button type="button" pButton pRipple label="Export" icon="pi pi-file-excel"
class="p-button-success p-mr-2"
pTooltip="XLS" tooltipPosition="bottom"></button>
</div>
</div>
</div>
</div>
Итак, в основном первая строка:
<app-employee-add-form [displayNewEmployeeDialog]="displayNewEmployeeDialog"></app-employee-add-form>
Затем я определил новую кнопку, которая вызовет метод, чтобы отобразить диалоговое окно, определенное в дочернем компоненте.
определите дочерний компонент, который будет отображать модальный параметр, который привязывает родительский компонент displayNewEmployeeDialog к displayNewEmployeeDialog дочернего модального компонента, чтобы показывать или не показывать модальный параметр на странице родительского компонента.
Это связанный машинописный код моего родительского компонента:
@Component({
selector: 'app-employee-list',
templateUrl: './employee-list.component.html',
styleUrls: ['./employee-list.component.scss']
})
export class EmployeeListComponent implements OnInit {
displayNewEmployeeDialog = false;
customers: Customer[];
selectedCustomers: Customer[];
representatives: Representative[];
statuses: any[];
loading: boolean = true;
@ViewChild('dt') table: Table;
constructor(private customerService: CustomerService, private primengConfig: PrimeNGConfig) { }
ngOnInit() {
this.customerService.getCustomersLarge().then(customers => {
this.customers = customers;
this.loading = false;
});
this.representatives = [
{name: "Amy Elsner", image: 'amyelsner.png'},
{name: "Anna Fali", image: 'annafali.png'},
{name: "Asiya Javayant", image: 'asiyajavayant.png'},
{name: "Bernardo Dominic", image: 'bernardodominic.png'},
{name: "Elwin Sharvill", image: 'elwinsharvill.png'},
{name: "Ioni Bowcher", image: 'ionibowcher.png'},
{name: "Ivan Magalhaes",image: 'ivanmagalhaes.png'},
{name: "Onyama Limba", image: 'onyamalimba.png'},
{name: "Stephen Shaw", image: 'stephenshaw.png'},
{name: "XuXue Feng", image: 'xuxuefeng.png'}
];
this.statuses = [
{label: 'Unqualified', value: 'unqualified'},
{label: 'Qualified', value: 'qualified'},
{label: 'New', value: 'new'},
{label: 'Negotiation', value: 'negotiation'},
{label: 'Renewal', value: 'renewal'},
{label: 'Proposal', value: 'proposal'}
]
this.primengConfig.ripple = true;
}
onActivityChange(event) {
const value = event.target.value;
if (value amp;amp; value.trim().length) {
const activity = parseInt(value);
if (!isNaN(activity)) {
this.table.filter(activity, 'activity', 'gte');
}
}
}
onDateSelect(value) {
this.table.filter(this.formatDate(value), 'date', 'equals')
}
formatDate(date) {
let month = date.getMonth() 1;
let day = date.getDate();
if (month < 10) {
month = '0' month;
}
if (day < 10) {
day = '0' day;
}
return date.getFullYear() '-' month '-' day;
}
onRepresentativeChange(event) {
this.table.filter(event.value, 'representative', 'in')
}
showNewEmployeeDialog() {
console.log("showNewEmployeeDialog() START !!!");
this.displayNewEmployeeDialog = true;
}
}
Basically the only thing that are related to my problem are this line that define the displayNewEmployeeDialog as false in order to avoid to show the dialog child component when I load the page of this parent component:
displayNewEmployeeDialog = false;
and this method that change the value of this variable in order to open my dialog when the user click on the New button:
showNewEmployeeDialog() {
console.log("showNewEmployeeDialog() START !!!");
this.displayNewEmployeeDialog = true;
}
Тогда это код представления моего дочернего компонента:
<p-dialog header="Inserire un nuovo impiegato"
maximizable="true"
[(visible)]="displayNewEmployeeDialog"
position="top"
[style]="{width: '50vw'}">
<form [formGroup]="newEmployeeForm" id="addEmployeeForm">
<div class="row">
<div class="col-2">
<p>Nome</p>
</div>
<div class="col-10">
<input id="name" formControlName="name" type="text" pInputText />
</div>
</div>
</form>
<p-footer>
<span class="p-buttonset">
<button pButton type="button" label="Save" icon="pi pi-check"></button>
<button pButton type="button" label="Cancel" icon="pi pi-times" (click)="closeDialog()"></button>
</span>
</p-footer>
</p-dialog>
На данный момент он содержит минималистичную форму. Для него устанавливается значение visible, когда для значения displayNewEmployeeDialog установлено значение true, в противном случае оно будет невидимым.
И это машинописный код этого дочернего компонента:
@Component({
selector: 'app-employee-add-form',
templateUrl: './employee-add-form.component.html',
styleUrls: ['./employee-add-form.component.scss']
})
export class EmployeeAddFormComponent implements OnInit {
@Input()
displayNewEmployeeDialog: boolean;
newEmployeeForm: FormGroup;
constructor() { }
ngOnInit(): void {
console.log("bla");
}
closeDialog() {
this.displayNewEmployeeDialog = false;
this.ngOnInit();
}
}
Как вы можете видеть, я просто импортирую значение displayNewEmployeeDialog из родительского элемента, используя декоратор @Input(), чтобы обнаруживать изменения и открывать и закрывать мой модальный.
Проблема в том, что когда я впервые нажимаю кнопку «Добавить» в родительский компонент, мой модальный компонент будет правильно открыт, как показано здесь:
Проблема в том, что при закрытии этого модального элемента нажатием на значок X в правом верхнем углу или на кнопку «Отмена», если я попытаюсь открыть новый модальный элемент (снова нажав на кнопку «Добавить» родительского компонента), модальный элемент не появляется. У меня нет ошибки в консоли.
Почему такое поведение? При нажатии на кнопку «Добавить» родительского компонента значение должно быть получено дочерним компонентом как «true», поэтому модальное значение должно отображаться снова, но этого не происходит? Чего мне не хватает? Как я могу исправить эту проблему?
Ответ №1:
Вам нужно определить два свойства, свойство ввода и свойство вывода, чтобы выдать событие on close. Свойство displayNewEmployeeDialog должно управляться только родительским компонентом:
child.component.ts
export class EmployeeAddFormComponent implements OnInit {
@Input()
displayNewEmployeeDialog: boolean;
@Output
onDialogClose: EventEmitter<any> = new EventEmitter();
//..
closeDialog() {
this.onDialogClose.emit();
}
}
parent.component.html
<app-employee-add-form [displayNewEmployeeDialog]="displayNewEmployeeDialog" (onDialogClose)="closeDialog()"></app-employee-add-form>
parent.component.ts
closeDialog(): void {
this.displayNewEmployeeDialog=false;
}