简体   繁体   中英

Updating UI With ASYNC Pipe and Returned Observable<{}>

I am in quite a pickle and it could be the approach that I have been taking with learning about rxJS and Observables.

Preface

Our application uses Angular to connect to our public API layer (C#). The type of object that is returned from my ASYNC call is of Observable< ListResultDtoOfNoteDto > . This stream is passed to a child component which loops through the items. This same stream also allows a user to add new note of type NoteDto or edit notes. Ideally when these actions are done the list of notes will reflect the updated change without having to call the same service call for getting the notes again.

Code

[notes.component.html]

<div *ngIf="(notes$ | async)?.items as notes; else loading">
    <note-card [noteData]="notes" (noteClick)="editNote($event)"></note-card>
</div>
<ng-template #loading>
    <div class="notes__container">
        <div class="note-card">
            <div class="note-card__primary-action">
                <div class="note-card__head">
                    <h2 class="note-card__title note-card-typography--headline1 text-center">Loading...</h2>
                </div>
            </div>
        </div>
    </div>
</ng-template>

[notes.component.ts]

import ...

@Component({
    ...
})
export class NotesComponent extends AppComponentBase implements OnInit {
    constructor(
        ...
        private _noteService: NoteServiceServiceProxy
    ) {
        super(injector);
    }

    public notes$: Observable<ListResultDtoOfNoteDto>;
    public userId: number;
    ...

    ngOnInit() {
        ...
        this.getNotes();
        ...
    }

    getNotes(): void {
        /*
            Binding to ASYNC pipe; which doesn't need a subscription since it is automatic?
            Returns type: Observable<ListResultDtoOfNoteDto> which is an array of NoteDto
        */
        this.notes$ = this._noteService.getUserNotes(this.userId, null);
        ...
    }
    ...

    public saveNote(note: NoteDto, mode: string) {
        if (mode === 'new') {
            this._noteService.addNote(note).subscribe(() => {
                this.cleanUp();
                this.getNotes();
                this.notify.info(this.l('SavedNoteSuccessfully'));
            });
        } 
        ...
    }
}

All of the functionality minus the clickEvent in the child happens within the parent. Which loads a form (reactive form methodology) that can take a new note and save or edit an older note to update.

My issue

I am just wanting a way to save the note and update the list without having to call this.getNotes() again in the subscription when a new note is added.

(I can provide more details if needed!)

EDIT: Forgot to show save method currently

One way in which you can achieve this is to have a private BehaviorSubject inside of your NoteServiceServiceProxy which will always contain the latest value of notes.

Like: private _notes = new BehaviorSubject<ListResultDtoOfNoteDto>(null)

  • and you publicize a function that is only for consumers to subscribe.
  • Your API call will only update the subject with the response
public getNotes(): Observable<ListResultDtoOfNoteDto> {
    return this._notes.asObservable();
}

public getNotesFromApi(args): {
    // Api request
    this.httpClient.get().pipe(tap(result) => this._notes.next(result))
    // etc...
}

Then all you need to do in your component is declare your observable something like

notesData = this. _noteService.getNotes();

inside init just make request to API to get the notes and it will automatically update your notesData which should be subscribe on your template via async pipe output.

When you save all you need to do is just add a concatMap at the end so that your save goes first then you request the update from your api.

So something like

    this._noteService.addNote(note).pipe(
        concatMap(() => this._noteService.getNotesFromApi()))
        .subscribe();

This again will update your notesData variable which is on the template.

I hope you understand how this flow works and if not feel free to ask.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM