Convert JSON Object to Internal Model


#1

Hi everyone!. I have this problem: From websocket i received one object json and need add this object to model.

let objWs = {
                "data": {
                    "id": 1,
                    "type": "notifications",
                    "attributes": {
                        "topic": obj.topic,
                        "comment": obj.comment
                    },
                    "relationships": {},
                    "meta": {}
                }
            };

this.get('model.notifications').unshiftObject(objWs);

But return this message: “Uncaught TypeError: internalModel.getRecord is not a function”

Also try this:

this.get('model.notifications').unshiftObject(this.get('store').normalize("notification", objWs));

Return this message: “Uncaught TypeError: Cannot read property ‘replace’ of undefined”

What is the correct way to transform a json object to an internal model?. I need this record to be automatically added to a #each that I have in the template.

Thanks!!


#2

try createRecord method from store https://emberjs.com/api/ember-data/2.16/classes/DS.Store/methods/createRecord?anchor=createRecord


#3

Hi @CezaryH thanks for your answer.

I try this:

this.get('store').createRecord('notification', {
                topic: obj.topic,
                comment: obj.comment
            }) 

Now, no error returned, but I do not see the record in the #each of the template. Is not added.

Thanks!


#4

are iterating over notifications from store ? you need to link it. Try ember inspector - you’ll see there if it’s in the store


#5

Yes, It is in the store, check this:

The #each is not updated :frowning:

Capable because the id is not there?


#6

should work without ID, how you set property that you iterate over ?


#7

Update this:

this.get('store').createRecord('notification', {
                topic: obj.topic,
                comment: obj.comment,
                isSeen: false,
                date: new Date()
            });

This is my #each

{{#each model.notifications as |notification|}}
                                    <div class="item">
                                        {{#if notification.topic }}
                                            <i class="alarm outline icon"></i> {{gettext "New topic"}}
                                            {{#link-to "topic" notification.topic.topicid notification.topic.slug}}
                                                {{ notification.topic.title }}
                                            {{/link-to}}
                                            {{gettext "By"}} {{ notification.topic.username }}
                                        {{else}}
                                            <i class="reply icon"></i> {{ notification.comment.username}}
                                            {{#link-to "topic" notification.comment.topicid notification.comment.slug}}
                                                {{ notification.comment.title }}
                                            {{/link-to}}
                                        {{/if}}
                                    </div>
                                    <div class="line-separator"></div>
                                {{/each}}

The code is in the controller application.js and the html in the application.hbs. This is because is all app.


#8

I already found the solution.

let record = this.get('store').createRecord('notification', {
                topic: obj.topic,
                comment: obj.comment,
                isSeen: false,
                date: new Date()
            });

 this.get('model.notifications').unshiftObject(record._internalModel);

Many thanks!!


#9

I wouldn’t use _internalModel as it’s internal property. you have issue in model method, that’s why template doesn’t know about store change


#10

That’s OK?

this.get('model.notifications').unshiftObject(record);


#11

What does the model() function look like in the application route? The use of model.notifications looks suspicious to me in the use case you described.


#12

Hi @Chris_Lincoln check this: https://github.com/mapeveri/muss/blob/master/static/muss/app/routes/application.js#L17


#13

Sorry for the diversion. What you had for model.notifications is correct. However, there may be an issue with the how you are handling the promise to the RSVP.hash(). What behavior do you get if you omit the .then() ?


#14

In totalNotifications?. If so, then in the template I have to access model.data.


#15

The response that is passed when the RSVP.hash resolves will have the same shape as the hash passed in the .hash() method. It should look like { notifications : … totalNotifications : … }

I use RSVP.hash() all over the place, and I have to admit that the fact that the code on line 24 is working at has me scratching my head.


#16

Also, if you want a createRecord() to appear in a template along with a list of records fetched in a model() hook, you need to use one of the DS.Store methods that returns a RecordArray. .query() returns a slightly different animal when resolved, and templates are synced with changes.

See the last note here: https://www.emberjs.com/api/ember-data/2.15/classes/DS.Store


#17

You want to use store.push() or store.pushPayload() instead of createRecord() when adding the notification json to the notifications list.

const model = this.get('store').push(objWs);
this.get('model.notifications').pushObject(model);

#18

Hi, try to convert your notifications to array with toArray() method before returning them from model hook: this.get('store').query('notification', {"user": user_id, "limit": 10}).then(notifications => notifications.toArray())