Replace Ember.ArrayController.create() will not resolve belongTo relationships | ember upgrade 3.x

戏子无情 提交于 2019-12-11 05:37:26

问题


I'm in the process of upgrading and I'm facing issues because ArrayController is being deprecated.

In my old Ember 1.13 route I'm using

model/announcement.js

export default DS.Model.extend( {


  id:DS.attr('string'),
  title: DS.attr( 'string' ),
  description: DS.attr( 'string' ),
  published: DS.attr( 'boolean' ),
  publishedAt: DS.attr( 'date' ),

  course: DS.belongsTo( 'course' ),
  author: DS.belongsTo( 'profile', { async: true } ),

  viewed: false,
  isNew: true,

}

serializer/announcement.js

import DS from 'ember-data';
import ApplicationSerializer from 'mim/serializers/application';

export default ApplicationSerializer.extend( DS.EmbeddedRecordsMixin, {

  keyForRelationship: function( key ) {

    return key !== 'author' ? key : 'id';
  }
} );

routes/announcement.js

 setupController: function( controller, model ) {

    this._super( ...arguments );

     var announcements = Ember.ArrayController.create( {

          model: model,
          sortProperties: [ 'publishedAt' ],
          sortAscending: false
        } );

        controller.set( 'model', announcements );
  },

In the controller of the route announcement, follows:

controller/announcement.js

publishedAnnouncements: Ember.computed( 'model.[]', 'model.@each.published', 'model.@each.viewed', function() {

    var published = this.get( 'model' ).filterBy( 'published', true ),
        announcements = Ember.A();

    announcements.pushObjects( published.filterBy( 'viewed', false ) );
    announcements.pushObjects( published.filterBy( 'viewed' ) );

    return announcements;
  } ),

so in the template im running a for each loop to render all announcements like

templates/announcements.hbs

  {{#each publishedAnnouncements as |announcement|}}
        {{announcement.author.firstName}}
      {{/each}} 

After the ember upgrade 3.5 I have changed these to the following:

model/announcement.js

export default DS.Model.extend( {

  id:DS.attr('string'),
  title: DS.attr( 'string' ),
  description: DS.attr( 'string' ),
  published: DS.attr( 'boolean' ),
  publishedAt: DS.attr( 'date' ),

  course: DS.belongsTo( 'course' ),

// remove async true from profile

  author: DS.belongsTo( 'profile'),

  viewed: false,
  isNew: true,

}

serializer/announcement.js

import DS from 'ember-data';
import ApplicationSerializer from 'mim/serializers/application';

export default ApplicationSerializer.extend( DS.EmbeddedRecordsMixin, {

  keyForRelationship: function( key ) {

    return key !== 'author' ? key : 'id';
  }
} );

routes/announcement.js

setupController: function( controller, model ) {

    this._super( ...arguments );

     //removed arrayController from here and assigned model

        controller.set( 'model', model );
  },

controller/announcement.js

sortProperties: ['publishedAt:desc'], sortedModel: computed.sort('model', 'sortProperties'),

publishedAnnouncements: Ember.computed( 'model.[]', 'model.@each.published', 'model.@each.viewed', function() {

   //getting model by local computed property defined above.arrayController sort is doing with above method by sortPropteries 
   var published =this.get('sortedModel').filterBy( 'published', true);
        announcements = Ember.A();

    announcements.pushObjects( published.filterBy( 'viewed', false ) );
    announcements.pushObjects( published.filterBy( 'viewed' ) );

    return announcements;
  } ),

templates/announcements.hbs

  {{#each publishedAnnouncements as |announcement|}}
        {{announcement.author.firstName}}
      {{/each}} 

Then the announcement.author.firstname is undefined in ember 3.5 but if it is not a belongsTo relationship it will be there (example announcement.publishedAt)

I have no clue what I missed or what I did wrong here.

I am attaching a screenshot here of a console log which I did in the controller published variable.

Ember 1.13

Ember 3.5

your answers make me better understand the problem. the api returns a custom version of data thats why embeddedRecordsMixin used this is the api payload for course

{
  "courses": [{
    "created_at": "2016-11-22T09:37:53+00:00",
    "updated_at": "2016-11-22T09:37:53+00:00",
    "students": ["01", "02"],
    "coordinators": ["001", "002"],
    "programme_id": 1,
    "announcements": [{
      "created_at": "2016-11-23T08:27:31+00:00",
      "updated_at": "2016-11-23T08:27:31+00:00",
      "course_id": 099,
      "id": 33,
      "title": "test announcement",
      "description": "please ignore",
      "published_at": "2016-11-23T08:27:31+00:00",
      "published": true
    }, {
      "created_at": "2016-11-25T07:13:18+00:00",
      "updated_at": "2016-11-25T07:13:18+00:00",
      "course_id": 04,
      "id": 22,
      "title": "test before ",
      "description": "test",
      "published_at": "2016-11-25T07:13:18+00:00",
      "published": true
    }]
}

回答1:


Where to start debugging:

Have a look at what your API returns:

  1. Spin up your local Ember app and API.
  2. Open localhost:4200 in Chrome.
  3. Open the network tab in dev tools.
  4. Refresh the page to trigger the network request I assume is in your route's model() hook.
  5. Look at the JSON returned by your API. Is it JSON API compliant?
  6. Open the data tab in Ember Inspector.
  7. After the request occurred, did the author you are expecting to see populate the store?
  8. If yes, does he have firstName or is it undefined?

If all positive, then we can probably rule out issues with the request, API and serialisers.

Seeing this serializer:

// app/serializers/announcments.js

import DS from 'ember-data';
import ApplicationSerializer from 'mim/serializers/application';

export default ApplicationSerializer.extend( DS.EmbeddedRecordsMixin, {
  keyForRelationship: function( key ) {
    return key !== 'author' ? key : 'id';
  }
} );

The mixin EmbeddedRecordsMixin implies your API returns embedded data which is quite uncommon for JSON API compliant responses. This is the only serializer you will need if all according this spec:

// app/serializers/application.js

import JSONAPISerializer from 'ember-data/serializers/json-api';

export default JSONAPISerializer.extend({});

The data coming from your API should be looking like:

{
  "data": [{
    "type": "announcement",
    "id": "1",
    "attributes": {
      "message": "...",
    },
    "relationships": {
      "author": {
        "data": { "type": "profile", "id": "9" }
      },
    }
  }],
  "included": [{
    "type": "profile",
    "id": "9",
    "attributes": {
      "firstName": "John",
      "lastName": "Johnson"
    },
  }]
}



回答2:


Ember is designed to be back-end agnostic. With the serialisers you can convert all JSON from incoming server responses to suit the Ember Data store. Similarily you use adapters to convert outgoing server requests to suit your back-end.

I recommend reading this doc:

https://guides.emberjs.com/release/models/customizing-serializers/

Then choose from:

  • JSON API serializers (recommended)
  • REST serializers
  • Active Model serializers
  • Create your own custom serializer
  • Embedded records mixin


来源:https://stackoverflow.com/questions/53255803/replace-ember-arraycontroller-create-will-not-resolve-belongto-relationships

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