Updating Polymer Component with data from outside

2019-09-10 21:53发布

问题:

This should be a pretty normal task , and yet i am missing something .

I am trying to integrate Socket.io with Polymer [ using the chat application ] - Deciding to change the MessageList and the individual messageItem as Polymer components . SocketIo exposes a customEvent to be thrown from server , which sends the message as data , which then is being assigned to a property on the custom element .

This is the MessageList element .

<link rel="import" href="/polymer/polymer.html">
<link rel="import" href="message.html">

<dom-module id='message-list'>
<template>

    <style>

    </style>

    <ul id="messages">
        <template is='dom-repeat' items="{{messageList}}" is="auto-binding">
            <li>
                <message-item message = "{{item}}"></message-item>
            </li>
        </template>
    </ul>

</template>
<script>
    var messageListElement = Polymer({
        is : 'message-list',
        properties : {
            messageList : {
                type : Array,
                observer: '_messageListChanged',
                reflect : true ,
                value : function() {
                    return [{'inputMessage' : 'Welcome to the Chat' , 
                    'nickName' : 'System' , 'msgTime' : new Date()}]
                }
                //, notify : true
            }
        },

        _messageListChanged: function(newValue , oldValue) {
            console.log("Data changed");
        },

        created : function() {
            console.log("messagelist created");
        },

        ready : function() {
            console.log("messagelist ready");
        },

        attributeChanged : function() {
            console.log("messagelist attributeChanged");
        }
    });
</script>

On the index.html Page -

var self = this;
socket.on('chatMessage' , function(msg) {
        self.messages.push(msg);
        console.log(self.messages);

        document.querySelector('message-list').messageList = self.messages;

    });

With all of this.. Anytime a client sends a message , the self.messages - posts the total set of messages , but the "_messageListChanged" of the custom elements gets called only the first time .

There are similar questions - Updating a polymer element property with data from API call

However assigning the data , works only for the first time . Also i would like to be able to do it without using ajax-iron and stuff .

回答1:

In addition to using the Polymer API for array mutations (as Alon has pointed out in his answer), you need to install an observer for array mutations. The observer you have now will only fire when you assign a new array instance, but not when you add or remove elements from your array.

    properties : {
        messageList : {
             type : Array,
             value : function() {
                return [{'inputMessage' : 'Welcome to the Chat' , 
                'nickName' : 'System' , 'msgTime' : new Date()}]
            }
        }
    },
    observers: [
        '_messageListChanged(messageList.splices)'
    ],

Note that this kind of observer takes a single argument, a change record.

Your observer method should accept a single argument. When your observer method is called, it receives a change record of the mutations that occurred on the array.



回答2:

The problem is that you use push. polymer has his own push function.The regular push does not trigger the observers, and all the change events.

this.push('array',value)

But for you, you can solve it like this:

var self = this;
socket.on('chatMessage' , function(msg) {
    self.messages.push(msg);


    document.querySelector('message-list').messageList = self.messages.slice();

});

The slice will create new array. And it will trigger all the change in the array.



回答3:

please try adding reflectToAttribute:true to your messageList property.

if you still don't get it solved try to so this

self.myimmutedArray JSON.parse(JSON.stringify(self.messages))

before document.querySelector('message-list').messageList = self.myimmutedArray;

reason could be the javascript array push or slice will not refelect in polymer's dirty checking

if you use below code in the a polymer component. you must follow polymer's array changes like

this.push('messages', {title:'hey'});

var self = this;
socket.on('chatMessage' , function(msg) {
        self.messages.push(msg);
        console.log(self.messages);

        document.querySelector('message-list').messageList = self.messages;

    });