Correct way to make an ajax call from EmberJs comp

2020-07-11 08:41发布

问题:

I would like to know what is the correct way to make an ajax call from an ember component. for example

I want to create a reusable component that makes an employee search by employee's Id, then when the response comes back from the server I want to update the model with the data from the ajax response.

I don´t know if this is the correct way to do it, I'm really new on emberjs.

export default Ember.Component.extend({
ajax: Ember.inject.service(),
actions: {
    doSearch() {
        showLoadingData();
        var self = this;
        this.get('ajax').post('http://server.ip.com/api/v1/getEmployee', { "id": this }).then(function(data) {
            self.set('model.name', data.name);
            self.set('model.position', data.position);
            hideLoadingData();
        });
    }
}});

回答1:

EDIT: I misunderstood the question, so here's an updated version of my answer:

First, I think you should switch to using ember-data. Then fetching an employee by id would just resolve to calling this.get("store").find("employee", id).

If you wish to use plain ajax, I suggest that you create a Service that encapsulates specifics (API endpoint URL, data format, and so on) and only exposes simple methods for finding and updating models.

And finally, to comply with the "data down, actions up" pattern, you shouldn't update the model in this component. Instead send an action to the parent controller/component. Like so:

app/components/employee-selector.js (the component you're writing):

export default Ember.Component.extend({
  actions: {
    updateId(id) {
      Ember.$.post("http://server.ip.com/api/v1/getEmployee", { id: params.id }.then((response) => {
        this.sendAction("select", response);
    });
  }
});

app/templates/new/it-request.hbs:

{{employee-selector select=(action "selectEmployee")}}

app/controllers/new/it-request.js:

export default Ember.Controller.extend({
  actions: {
    selectEmployee(employeeData) {
      this.set("model.name", employeeData.name);
      this.set("model.position", employeeData.name);
    }
  }
});

Old answer:

An idiomatic solution would be to do this in a Route.

First you should add a route in app/router.js:

this.route("employees", function() {
  this.route("show", { path: ":id" });
}

Than define the route in app/employees/show/route.js:

import Ember from "ember";

export default Ember.Route.extend({
  model(params) {
    return new Ember.RSVP.Promise((resolve, reject) {
      Ember.$.post("http://server.ip.com/api/v1/getEmployee", { id: params.id }.then(
        (response) => { resolve(response) },
        reject
      );
    });
  }
});

(The only reason I wrapped everything in a new promise is to allow response customization - just replace resolve(response) with a code that transforms the raw response from the server and invoke resolve with this transformed version).

But if you'll have more communication with the API, and I suppose that you will, I suggest that you try using ember-data or any other data layer library for ember (probably Orbit).

Or at least write a service that abstracts away all communication with the API and use it anywhere you'd use raw ajax requests.



回答2:

I was using Ember class directly in action so it looked like this

actions: {
  doSomething() {
    Ember.$.post('http://your-api-endpoint', data).then(function(response){ /* your callback code */});  
  }
}

And other way to communicate with BE is to use Ember Store (as you said) then in route you can get model from BE

example

App.PressRoute = Ember.Route.extend({
    route: "press",
    controllerName: 'press',
    model: function(params) {
        var controller = this.controllerFor("Press");

        if(controller.get("loaded") == false) {
            controller.set("loaded",true);
            return this.store.find('Article',{limit: 200});
        }
        else return this.store.all('Article');
    }, 
    renderTemplate: function() {
        this.render('press');
    }
});


回答3:

There are several ways you can do this!

Firstly, Ember has a convient alias for jQuery: Ember.$. So, if you're familiar jQuery, this should be easy enough.

You can also use Ember's RSVP package. There's a good example here on how to make a request and do something with the response.

Thirdly, you can the ember-ajax service.

But what you're asking (update the model with the data from the ajax response) is already built into Ember Data. You'll need to map your API into what ember expects with an adapter and/or a serializer. Once your service is transformed into what Ember expects, you can query your server for a single record then save it.