Search code examples
rxjsangular2-template

Using ngModel with async pipe in template


I have something like this right now in my template

<ng-container *ngIf="state | async as stateObject">
  <select [(ngModel)]="stateObject.name">
    <option>Select</option>
  </select>
<ng-container>

My question is how do I get the value of stateObject.name inside my component, because I dont have any subscription in my component.


Solution

  • My question is how do I get the value of stateObject.name inside my component, because I dont have any subscription in my component.

    You could do

    <select [(ngModel)]="stateObject.name" (ngModelChange)="doSomething($event)">
        <!-- … -->
    </select>
    

    And then in your component

    doSomething (model: State): void {
        console.log(model); // or whatever
    }
    

    But that doesn't strike me as the best idea. It might be better to not use the async pipe here and instead manage the subscription explicitly in your component:

    <ng-container *ngIf="stateObject">
        <select [(ngModel)]="stateObject">
            <!-- … -->
        </select>
    </ng-container>
    
    // ===
    
    @Component({ … })
    public YourComponent extends Component implements OnDestroy {
    
        public stateObject: State;
        private destroy$ = new Subject();
    
        constructor(private state: StateService) {
            state
                .takeUntil(this.destroy$)
                .subscribe(state => this.stateObject = state);
        }
    
        public ngOnDestroy(): void {
            this.destroy$.next();
            this.destroy$.complete();
        }
    
    }
    

    This would also give you better control over what to do if, for example, state emits while your form is dirty.