Я пытаюсь добиться довольно простого поведения <select>
: вернуться к предыдущему значению, если пользователь отменил изменение. На самом деле, мне это удалось, но это стоило мне нескольких часов, и я все еще недоволен реализацией, потому что это не так очевидно и сложно.
Итак, вот шаблон:
<select id="states" class="form-control" name="states" [ngModel]="selectedState"
(ngModelChange)="onStateChange(selectedState, $event)">
<option [ngValue]="null">All</option>
<option *ngFor="let state of states" [ngValue]="state">{{state.name}}</option>
</select>
и компонент:
export class AppComponent {
selectedState: State = null;
states: State[] = [
{ name: 'Alabama', population: 100000 },
{ name: 'Alaska', population: 50000 }
];
onStateChange(previousState: State, state: State): void {
// If we're changing state from "All" to any, it's OK
if (previousState === null) {
this.selectedState = state;
return;
}
// Otherwise we want the user to confirm that change
if (confirm('Are you sure you want to select another state?')) {
this.selectedState = state;
} else {
// But instead of just `this.selectedState = previousState;`
// I need to proceed with below dirty hack.
// Step 1: Changing property value, which is bound to `[ngModel]`,
// to any, except for the current one, so `null` is OK
this.selectedState = null;
// Step 2: Reverting this property value to the previous one,
// which is, ridiculously, already set as the previous one,
// because we're reverting `this.selectedState`,
// while passing exactly the same `this.selectedState`
// to this method as a `previousState` parameter,
// so we're actually doing `this.selectedState = this.selectedState;`,
// but in not-so-obvious form.
// This works only kind of asynchronously,
// after call stack is clear.
setTimeout(() => {
this.selectedState = previousState;
}, 0);
}
}
}
Я надеюсь, что комментарии говорят сами за себя, по крайней мере, я попытался написать их, чтобы они были такими.
Как я уже упоминал в комментариях, простой this.selectedState = previousState;
не работает, равно как и пропуск setTimeout()
. Я тоже это попробовал, но не повезло:
this.selectedState = previousState;
this.changeDetectorRef.detectChanges();
Мое решение основано на этом ответе , и да, я видел и этот , но он просто не работает для меня, потому что я связываюсь <select>
к объекту, а не к скалярному значению.
Демонстрация: https://angular -hkaznb.stackblitz.io
Варианты комплектации:
Угловой: 6.0.0