[英]Updating Ngrx store from material combo-box and then binding to the returned ngrx store data
我剛剛開始接觸Ngrx。 我已經連接了各種控件以進行更新,然后從我的商店中返回數據。 文本框和復選框按預期工作,但組合框是不同的層。 我無法獲得正確的約束力。
以下是我面臨的問題:
1)當我更新組合框中的值時,setCurrentBadge函數被觸發兩次
2)我從名為<mat-select class="badge-codes-combobox">
的組合框中的列表中選擇的值不可見。
3)getCurrentBadge函數觸發,即使它位於ngInit生命周期鈎子中並且頁面未重新加載。
4)當我重新加載頁面時,getCurrentBadge函數觸發,但組合框不顯示返回的值。
就代碼而言,當組合框的值發生變化時,我需要使用badgeCodeSelected($ event)來觸發一次。 我需要[value] =“selectedBadge”來顯示所選的值,當重新加載頁面時,我需要組合框來顯示從商店返回的值)
這是我的代碼。
<div class="row">
<div class="col-md-4">
<app-declaration-type
[errorMessage] = "errorMessage$ | async"
[displayTypes] = "displayTypes$ | async"
[declarationTypes] = "declarationTypes$ | async"
[badges] = "badges$ | async"
[traderReference]= "traderReference$ | async"
[selectedBadge] = "selectedBadge$ | async"
(badgeSelected) = "badgeCodeSelected($event)"
(checked) = "checkChanged($event)"
(traderReferenceSet) = "onBlurTraderReferenceChange($event)"
>
</app-declaration-type>
</div>
</div>
@Component({
selector: 'app-declaration',
templateUrl: './declaration-shell.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DeclarationShellComponent implements OnInit {
errorMessage$: Observable<string>;
displayTypes$: Observable<boolean>;
declarationTypes$: Observable<Declarationtype[]>;
badges$: Observable<Badge[]>;
selectedDeclarationType$: Observable<string>;
selectedBadge$: Observable<Badge>;
traderReference$: Observable<string>;
constructor(private store: Store<fromDeclaraionType.State>) {}
ngOnInit() {
this.store.dispatch(new fromDeclarationTypeActions.LoadDeclarationType());
this.store.dispatch(new fromDeclarationTypeActions.LoadBadges());
this.errorMessage$ = this.store.pipe(select(fromDeclaraionType.getError));
this.displayTypes$ = this.store.pipe(
select(fromDeclaraionType.getToggleDeclarationTypes)
);
this.declarationTypes$ = this.store.pipe(
select(fromDeclaraionType.getDeclarationTypes)
);
this.selectedDeclarationType$ = this.store.pipe(
select(fromDeclaraionType.getCurrentDeclarationType)
);
this.badges$ = this.store.pipe(select(fromDeclaraionType.getBadges));
this.selectedBadge$ = this.store.pipe(
select(fromDeclaraionType.getCurrentBadge),
tap(x => console.log('About to fetch current badge from store {0}', x))
);
this.traderReference$ = this.store.pipe(
select(fromDeclaraionType.getTraderReference)
);
}
checkChanged(value: boolean): void {
console.log('About to dispatch toggle Display Declaration Types');
this.store.dispatch(
new fromDeclarationTypeActions.ToggleDeclarationTypes(value)
);
}
onBlurTraderReferenceChange(value: string) {
console.log('About to dispatch Set Trader Reference');
this.store.dispatch(
new fromDeclarationTypeActions.SetTraderReference(value)
);
}
badgeCodeSelected(value: Badge) {
console.log('About to dispatch Set Current Badge');
console.log(value);
this.store.dispatch(new fromDeclarationTypeActions.SetCurrentBadge(value));
}
}
<div class="declaration-type">
<mat-accordion>
<mat-expansion-panel
[expanded]="displayTypes === true"
(opened)="(displayTypes === true)"
>
<mat-expansion-panel-header
[collapsedHeight]="customCollapsedHeight"
[expandedHeight]="customExpandedHeight"
>
<mat-panel-title> <h4>Declaration Type</h4> </mat-panel-title>
<label>
<input
class="form-check-input"
type="checkbox"
(change)="checkChanged($event.target.checked)"
[checked]="displayTypes"
/>
Display Types?
</label>
</mat-expansion-panel-header>
<div class="controls-wrapper">
<div class="flex-container">
<div class="flex-item-declarationType">
<label class="field-label labelAlignment">
Decln Type [01]:
<mat-select class="declaration-type-combobox" [value]="selectedDeclarationType">
<mat-option
*ngFor="let declarationType of declarationTypes"
[value]="declarationType?.value"
>
{{ declarationType.value }}
</mat-option>
</mat-select>
</label>
</div>
<div class="flex-item-badgeCode">
<label class="field-label labelAlignment">
Badge Codes:
<mat-select class="badge-codes-combobox" [value]="selectedBadge" >
<mat-option (onSelectionChange)="badgeCodeSelected(badge)"
*ngFor="let badge of badges"
[value]="badge?.code">
<div>{{ badge.code }} - {{ badge.name }}</div>
</mat-option>
</mat-select>
</label>
</div>
</div>
<div class="flex-container">
<div class="flex-item-traderReference">
<label class="field-label labelAlignment">
Trader Reference [07]:
<input
matInput
type="text"
[(ngModel)]="traderReference"
class="trader-reference-inputBox"
(blur)="onTraderReferenceSet(traderReference)"
/>
<button
mat-button
*ngIf="traderReference"
matSuffix
mat-icon-button
aria-label="Clear"
(click)="traderReferenceValue = ''"
>
<mat-icon>close</mat-icon>
</button>
</label>
</div>
</div>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
@Component({
selector: 'app-declaration-type',
templateUrl: './declaration-type.component.html',
styleUrls: ['./declaration-type.component.scss']
})
export class DeclarationTypeComponent implements OnInit {
customCollapsedHeight = '40px';
customExpandedHeight = '40px';
@Input() errorMessage: string;
@Input() displayTypes: boolean;
@Input() declarationTypes: Declarationtype[];
@Input() badges: Badge[];
@Input() selectedDeclarationType: string;
@Input() selectedBadge: Badge;
@Input() traderReference: string;
@Output() checked = new EventEmitter<boolean>();
@Output() declarationTypeSelected = new EventEmitter<string>();
@Output() badgeSelected = new EventEmitter<Badge>();
@Output() traderReferenceSet = new EventEmitter<string>();
constructor() {}
ngOnInit(): void {}
checkChanged(value: boolean): void {
this.checked.emit(value);
}
badgeCodeSelected(value: Badge) {
this.badgeSelected.emit(value);
}
onTraderReferenceSet(value: string) {
this.traderReferenceSet.emit(value);
}
}
對於您來說,這將是一個轉變,但是我想分享一下,我有一個庫,除其他外,該庫具有內置指令以將表單控件綁定到商店。 最大的變化是您將需要構建StoreObject
而不是使用選擇器,並且您將不會編寫或處理任何操作。
該庫稱為ng-app-state
,綁定到表單控件的鍵在nasModel
指令中。 我會在下面給你一個想法。
假設您的復選框的值在商店中的位置如下:
class DeclarationTypeState {
badgeCode: string;
}
然后你會像這樣使用它:
@Component({
template: `
<mat-select [nasModel]="badgeCodeStore">
<mat-option ...></mat-option>
</mat-select>
`,
})
export class DeclarationTypeComponent {
badgeCodeStore: StoreObject<string>;
constructor(myStore: MyStore) {
this.badgeCodeStore = myStore('keyForDeclarationTypeState')('badgeCode');
}
}
這將對您的商店進行2向綁定,以使mat-select
與商店保持同步,並在用戶更改時在商店中編輯值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.