ListView does not refresh/update when a new value is added


#1

Hello everyone -

I’m using {N} + Angular 4 + Observables to get a ListView populated (working) and refreshed/updated when a new value is posted against a Rest API (doesn’t work). Below the code excerpt


app/models/user.ts

export class User {
       public name: string;
       public telephone: string; 
       public email: string;
       public password: string;

       public constructor(name: string, telephone: string, email: string, password: string){
           this.name = name;
           this.telephone = telephone;
           this.email = email;
           this.password = password;
       }
}

app/services/entre-users.service.ts

import { Injectable } from '@angular/core';
import { Http, Headers } from "@angular/http";
import { BehaviorSubject } from "rxjs/Rx";
import 'rxjs/Rx';

import { Config } from './../shared/config';
import { User } from './../models/user';



@Injectable()
export class EntreUsersService {

    public users$ = new BehaviorSubject<any>([]);

    constructor(private http: Http) { }


    listUsers() {
        return this.http.get(Config.apiUrl + "users/")
            .map(result => result.json());
    }



    createUser(data) {
        const headers = new Headers({ 'Content-Type': 'application/json' });
        this.users$.next(data);
        console.dump(this.users$);
        return this.http.post(Config.apiUrl + "users/", data, { headers: headers });
    }

}


The above “Config.apiUrl” is simply the path to the resource in the server. Working properly.

app/pages/users/users.page.ts

import { Component, OnInit } from "@angular/core";
import { Observable } from "rxjs/Rx";
import 'rxjs/Rx';

import { HeaderComponent } from "../../components/header-component/header.component";
import { MySearchBarComponent } from "../../components/my-search-bar/my-search-bar.component";
import { AppListComponent } from './../../components/list-component/app-list.component';
import { EntreUsersService } from './../../services/entre-users.service';
import { User } from './../../models/user';




@Component({
    selector: 'users-page',
    templateUrl: 'pages/users/users.page.html'
})
export class UsersPage implements OnInit {

    hint: String;
    actionBarTitle: String;
    clientPath: String;
    iconStatus = true;
    propertyTarget: String;
    
    public users: Observable<User>;



    public constructor(private entreService: EntreUsersService) { }

    public ngOnInit() {
        this.actionBarTitle = "Usuários"
        this.clientPath = "usercreateedit";         
        this.users =  this.entreService.listUsers();
    }

}



app/pages/users/users.page.html


<GridLayout rows="auto, auto, *" columns="*">
    <StackLayout row="0" col="0">
        <header-component [actionBarTitle]="actionBarTitle" [componentPathBack]="pathBack" [componentPath]="clientPath" [iconStatus]="iconStatus"></header-component>
    </StackLayout>
    <StackLayout row="1" col="0">
        <my-searchbar [theHint]="hint"></my-searchbar>
    </StackLayout>
    <StackLayout row="3" col="0">
        <ListView [items]="users | async" class="list-group">
            <ng-template let-item="item">
                <StackLayout class="list-group-item">
                    <Label class="h2" text={{item.name}}></Label>
                </StackLayout>
            </ng-template>
        </ListView>
</StackLayout>
<StackLayout>
    
</StackLayout>
</GridLayout>


app/pages/users/users-detail/user-create-edit.page.ts

import { Component, OnInit } from "@angular/core";
import { Http, Headers } from "@angular/http";
import { Observable, BehaviorSubject } from "rxjs";
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

import { CameraComponent } from "../../../components/camera-component/camera.component";
import { HeaderComponent } from "../../../components/header-component/header.component";
import { EntreUsersService } from './../../../services/entre-users.service';
import { User } from './../../../models/user';


@Component({
    selector: 'user-create-edit',
    templateUrl: 'pages/users/users-detail/user-create-edit.page.html'
})
export class UserCreateEditPage implements OnInit {

    actionBarTitle;
    clientPath;
    iconStatus;
    public users: Observable<User>;
   
    public usersForm: FormGroup;

    public constructor(private entreService: EntreUsersService, private fb: FormBuilder) {
        this.usersForm = this.fb.group({
            "name": ["", [Validators.required]],
            "telephone": ["", [Validators.required]],
            "email": ["", [Validators.required]],
            "password": ["", [Validators.required]]
        })
    
    }

    public ngOnInit() {
        this.actionBarTitle = "Criar novo usuário";
        this.clientPath = "";
        this.iconStatus = false;
    }

    public onSave(data): void {
        this.entreService.createUser(data)
        .subscribe(
            (response) =>  this.users = response.json()
        );
        this.usersForm.reset();
    }
   
}


app/pages/users/users-detail/user-create-edit.page.html

<header-component [actionBarTitle]="actionBarTitle" [componentPath]="clientPath" [iconStatus]="iconStatus"></header-component>
<ScrollView>
    <StackLayout [formGroup]="usersForm">
        <GridLayout rows="auto, auto, auto, auto, auto, auto" columns="auto, *" class="form-parent">
            <StackLayout row="0" col="0" class="form-child">
                <camera-component></camera-component>
            </StackLayout>
            
            <!--NAME-->
            <StackLayout row="0" col="1" class="form-child" verticalAlignment="bottom">
                <TextField hint="Insira um nome" formControlName="name"></TextField>
            </StackLayout>

            <StackLayout row="1" col="0" class="form-child">
                <Label text="{{'fa-phone' | fonticon}}" class="fa-gray" verticalAlignment="bottom"></Label>
            </StackLayout>
            
            <!--TELEPHONE-->
            <StackLayout row="1" col="1" class="form-child">
                <TextField hint="Número de telefone" formControlName="telephone"></TextField>
            </StackLayout>

            <StackLayout row="3" col="0" class="form-child">
                <Label text="{{'fa-envelope-o' | fonticon}}" class="fa-gray" verticalAlignment="bottom"></Label>
            </StackLayout>

            <!--EMAIL-->
            <StackLayout row="3" col="1" class="form-child">
                <TextField hint="Endereço de e-mail" formControlName="email"></TextField>
            </StackLayout>

            <StackLayout row="4" col="0" class="form-child">
                <Label text="{{'fa-key' | fonticon}}" class="fa-gray" verticalAlignment="bottom"></Label>
            </StackLayout>

            <!--PASS-->
            <StackLayout row="4" col="1" class="form-child">
                <TextField hint="Senha" formControlName="password" secure="true"></TextField>
            </StackLayout>
            
            <StackLayout row="5" col="1" class="form-child">
                <GridLayout rows="auto" columns="*, *">
                    <StackLayout row="0" col="0">
                        <Button class="form-button" text="Cancelar" (tap)="cancel()"></Button>
                    </StackLayout>
                    <StackLayout row="0" col="1">
                        <Button class="form-button" text="Salvar" (tap)="onSave(usersForm.value)"></Button>
                    </StackLayout>
                </GridLayout>
            </StackLayout>
        </GridLayout>

    </StackLayout>
</ScrollView>

It seems that I am not properly dealing with Observables. Any advice would be very appreciated!!!

Thank you,

Gilberto


#2

Hello everyone, Is there any advice or a tutorial regarding this subject? I’m really struggling with that!
thank you


#3

Please check here for some tips:

https://discourse.nativescript.org/t/getting-in-the-zone-js-handle-view-updates-with-zonedcallback-nathan-walker/516

Or here:

https://discourse.nativescript.org/t/force-reloading-page-when-navigate-to-same-route-with-different-params/1743/4


#4

Thank you! saved the day