Angular observable array, populated by an http request and manually added data

孤者浪人 提交于 2019-12-11 08:58:35

问题


I'm trying to get my head around observables in Angular 6, but I'm new to anything more recent than AngularJS and seriously struggling right now. I think I've gone through every tutorial I can find and searched extensively here, so hopefully I'm not missing anything, but happy to take friendly pointers...

What I'm trying to do is this:

  1. GET request to a backend API, returns a JSON array of items, and display that array in a component as a data list
  2. Allow a second component to POST new items to the backend, and also add that item to the list of items above

I'm guessing I'm describing an observable, because #1 needs to be asynchronous, but all the examples I've seen seem to only deal with one of the two steps, not both together. What am I missing?


回答1:


@1: GET request to a backend API, returns a JSON array of items, and display that array in a component as a data list

let's call this one ComponentA:

export class ComponentA {        
    arrayOfItems:Type[];
    constructor(private http:HttpClient) {}

    getDataFromAPI():Observable<Type[]> {
        this.http.get<Type[]>('api-get-url')
            .subscribe(
                (items) => {
                    //print them if you want;console.log('response from the api', items);
                    this.arrayOfItems = items;
                }
            )
    }
}

@2.1: Allow a second component to POST new items to the backend (omitted a part of the question on purpose)

export class ComponentB {  
    // let's assume this array is already populated
    // via you 2-way bindings or whatever means 
    newItems:Type[];
    constructor(private http:HttpClient) {}

    postDataToAPI():Observable<any> {
        this.http.post('api-post-url', this.newItem)
            .subscribe(
                response => console.log('response from the api', response);
            )
    }
}

@2.2 and also add that item to the list of items above

Everything ^ was straightforward, but now you gotta stop and think: I have something 'here' and something 'there'. How can I ... connect them? Ha! Connect! So I need some sort of mechanism to connect the 2 components. What do you do? You use a service! But a service whose purpose is to store a shared data set. You can call it DataStoreService.

Let's (re)write some code:

@Injectable()
export class DataStoreService() {
    items:Type[] = [];
    constructor(private http:HttpClient) {}

    getDataFromTheAPI():Observable<Type[]> {
            this.http.get<Type[]>('api-get-url')
                .subscribe(items => this.items = items)
    }

    postDataToTheAPI(itemToAdd:Type):Observable<any> {
            this.http.post('api-post-url', itemsToAdd)
                .subscribe(
                    (response) => {
                        // check if all is good, and add it to the 'items' array
                        addItem(itemToAdd);
                    }
            }
        )
    }

    getItems() {
        return this.items;
    }

    addItem(item:Type) {
        this.items.push(item);
    }
}

Now, your Component A changes to:

export class ComponentA implements OnInit{
    constructor(private dataStoreService: DataStoreService) {}

    ngOnInit(): void {
        this.dataStoreService.getDataFromTheAPI(); 
        // ^ will request the data from the API and store it 
        // inside the service
    }

    // and here you get a reference to that data
    get itemsReferenceFromService() {
        return this.jobsStoreService.getJobsArray();
    }
}

And ComponentB to:

export class ComponentB {
    newItem:Type;
    constructor(private dataStoreService: DataStoreService) {}

    // when you do this, if successful, addItem method
    // will also be called that will 'and also add that item to the list of items above'; as componentA only has a reference to the data in 
    // the service, the new item will be displayed it it
    this.dataStoreService.postDataToTheAPI(newItem);
}

Hope this answers your question. If you have any other doubts, say it loud. Info like urls were omitted.

A further improvement is to have another service that only handles the API calls, and keep the DataService clean just for storing purposes. That will ease testing.

Be aware that the lifespan of any Service/Component in angular is up untill the end user refreshed the page. The service described is not a persistence mechanism.




回答2:


That because it is two different things.

The first is an request that you are expecting data from. so you subscribe to it.

$newsletter = NewYorkTimesService.getData(); // this does some http stuff.
$newsletter.subscribe(newspaper => readData(newpaper) /*or whatever you want to do with json */ );

The second is a total different call (and different observable) to send data, where you are only really subscribing to know if it was successful.

$paymentResults = NewYorkTimesService.makePayment(paymentJSON); //this does http stuff too.
$paymentResults.subscribe(() => /*I guess it was successful */ , (error)=> /*it failed */);

The only thing they share is that they might be of the same called from the same service.




回答3:


Here is a basic example of doing it in Angular 5. I think the only thing that may be different between 5 and 6 is where the libraries you are importing come from.

@Injectable()
export class ItemsService {

  constructor(private http: HttpClient) { }

  private backendURL= "http://myurl.endpoint.com/";

  getItems(): Observable<IItem[]> {
    return this.http.get<IItem[]>(backendURL);
  }
  saveItems(items: IItem[]): Observable<IItem[]> {
    let options = { headers: new HttpHeaders({'Content-Type': 'application/json'})};
    return this.http.post(backendUrl, items, options);
  }
}

In your Component class you import the component and subscribe to it.

export class ItemComponent {

    itemList: Item[];

    constructor(private itemService: ItemService) { }

    ngOnInit() {

    this.itemService.getItems().subscribe(data => this.itemList = data);

    }  
}

Here is a pretty good tutorial that goes over the basics https://angular.io/tutorial



来源:https://stackoverflow.com/questions/51218241/angular-observable-array-populated-by-an-http-request-and-manually-added-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!