5

I'm just starting to learn Polymer. Here is a generic version of my polymer element:

<polymer-element name="my-element">
    <template>
        <style>
        :host {
            position:absolute;
            width: 200px;
            height: 100px;
            background-color: green;
        }
        </style>
        <p>my element</p>
        <content id="first-in"></content>
        <content id="second-in"></content>
    </template>
    <script>
    Polymer('my-element', {
        domReady: function() {
            alert(this.children[0].getAttribute('title')); 
            //this returns the value I want to observe
        }
    });
    </script>
<polymer-element>

The content tags are both being filled with another custom element (again slightly simplified):

<polymer-element name="in-element" attributes="title">
    <template>
        <style>
        ...
        </style>
        <p>{{title}}</p>
    </template>
    <script>
    Polymer('in-element', {
        title: 'me'
    });
    </script>
<polymer-element>

What I want to be able to do is call a function in my-element when the title attribute in (any) in-element (put in the content tag) is changed (by a click event or whatever). I'm not sure how to access this using observe or if I need to use mutationObserver, etc. How is this done/Is it possible?

tschie
  • 105
  • 2
  • 6

2 Answers2

8

Native properties like title are not observable by Polymer's data-binding system (e.g. Object.observe() [info]). It's generally a good idea to avoid them.

In your example, I've changed title to mytitle and published it with reflect: true so the property value reflects back to the attribute. This way you can completely avoid .getAttribute() and just check .mytitle on in-elements. You can also use {{mytitle}} in bindings.

You can do this through mutation observers [1]. Polymer provides onMutation to monitor children but you want to monitor attributes of children. For that, you need a pure MO:

ready: function() {
  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(m) {
      if (m.target.localName == 'in-element') { // only care about in-element
        console.log(m.attributeName, m.oldValue, m.target.mytitle);
      }
    });  
  });
  // Observe attribute changes to child elements
  observer.observe(this, {
    attributes: true,
    subtree: true,
    attributeOldValue: true
  }); 
}

Demo: http://jsbin.com/doxafewo/1/edit

In domReady(), I also changed your alert of this.children[0] to this.$.firstin.getDistributedNodes()[0].mytitle. Using getDistributedNodes() is better because you're guaranteed to have the nodes that are actually passing through the <content> insertion point [2].

ebidel
  • 23,921
  • 3
  • 63
  • 76
  • Thanks, this works great! Although, I'd like to call a custom function in my-element (called 'recalculate') during the mutations.forEach(). The function call works in ready() but not during the forEach(). How would I do this? – tschie Jul 11 '14 at 18:12
  • Sounds like you're forgetting to `bind(this)`. `mutations.forEach(function(m) {...}.bind(this));` – ebidel Jul 11 '14 at 21:56
  • You were right about the bind. That fixed things and allowed me to call the right function. But within the function I could no longer use `getDistributedNodes()`.However, I was able to use `this.children` to get the value I wanted. Is that the correct usage of `this.children`? – tschie Jul 11 '14 at 23:05
  • I'd have to see what you're doing, but it's probably another case where you need a `.bind(this)` on the function. JS scoping is fun! – ebidel Jul 11 '14 at 23:38
-1

For every attribute there is a watcher. So in your case it should be looking like this. Although there are 2 different implementation, one with attribute name as the first argument of the function.

Polymer('in-element', {
    title: 'me',
    titleChanged: function(oldVal, newVal) {
        // do something
    }
});

Polymer change watchers

hinogi
  • 36
  • 3
  • Native properties like `title` are not observable by Polymer's data-binding system (e.g. `Object.observe()`). See https://github.com/Polymer/docs/issues/90#issuecomment-19845774 – ebidel Jul 11 '14 at 15:13
  • Shall be a better warning from Polymer error handling system on things like this(properties not supported). I think id is another one. – saurshaz Nov 27 '14 at 12:17