Polymer attributes and variable mapping - html

I have a polymer element looking like this:
<polymer-element name="foo" attributes="bar">
<template>
<core-ajax
url="url.php"
params="{{ {last: bar} }}"></core-ajax>
{{bar}}
</template>
</polymer-element>
Though, when I create element, the attribute shows up on the page, but the ajax request is like url.php?last so it seems that variable is undefined.
Also, this.bar returns undefined.
How can I solve that?

Keep in mind core-ajax has been deprecated in polymer 1.0 to iron-ajax.
Anyway, is params bind being resolved properly?
Based on documentation for new iron-ajax element the sintax should be:
params='{"alt":"json", "q":"chrome"}'

Related

is it possible nest/inner dom-if where the second dom-if depends on value oberseved from the first dom-if block

I read carefully these threads
Polymer 1 nested dom-if within dom-repeat not updating when data changes
how to dynamically append an element to dom-if in Polymer?
How to access content of dom-if inside a custom element?
that may have some relation with my question but I didn't manage find any clue if I can do what I want and how.
In my company, there are several flows, each one for each business flow and each step of the flow is a screen coded as a Polymer 1 web component. All them are warraped in a root Polymer component which defines the route.
A simple exemple would be:
my-root-component:
<dom-module id="my-root-component">
<template>
<first-obrigatiory-page which-route={aValueReturnedFromFirstComponent}></first-obrigatiory-page>
<template is="dom-if" if="[[_isTrueFunction(aValueReturnedFromFirstComponent)]]" restamp>
<second-page which-sub-route={aValueReturnedFromSecondComponent}></second-page>
<template is="dom-if" if="[[_isTrueFunction(aValueReturnedFromSecondComponentComponent)]]" restamp>
<third-page ></third-page>
</template>
</template>
</template>
<script>
Polymer({
is: 'my-root-component',
behaviors: [doesntMatterHere],
properties: {
The first dom-if works as expected but the second seems not be taken in account and my third-page component is never showed.
I checked and the equivalent for _isTrueFunction(aValueReturnedFromSecondComponentComponent) is returning true.
Does aValueReturnedFromFirstComponent really return anything, because you should declare the attribute as which-route="{{aValueReturnedFromFirstComponent}}" instead of using simple { }.
Does the whichRoute (note the camelCase) property in the first-obrigatiory-page element have the notify: true property so the variable actually sends back the updated value?
I usually set observers on variables whenever dom-ifs don't update so I can see if they really change or not, and then set the variables myself through the console with document.querySelector('my-root-component').set('aValueReturnedFromFirstComponent', true) so I can see that the dom-if really updates.
A workaround could be to use events, but what you've done should work.

Polymer Component not independent from each other?

Given this simplified component:
<dom-module id="poly-component">
<template>
<paper-button raised onclick="dialog.open()">Button</paper-button>
<paper-dialog id="dialog"><h1>Paper Dialog Here!</h1></paper-dialog>
</template>
<script>
Polymer({
is: 'poly-component'
})
</script>
which does nothing more than open the dialog on clicking the button.
This module works when it used once on a page.
But when it is inserted twice
[...]
<dom-module id="polyTest-app">
<template>
<h2>Hello [[prop1]]</h2>
<poly-component></poly-component>
<poly-component></poly-component>
</template>
[...]
it doesn't work anymore.
A click on the button leads to a:
(index):1 Uncaught TypeError: dialog.open is not a function
Am I missing something?
The code for this example can be found here: Example Code on GitHub
Your code cannot work because you're not binding the event handler correctly.
A built-in handler like onclick tries to execute the bit of code in global scope where dialog doesn't exist. Hence the error.
Here's how you can rewrite your code
<dom-module id="poly-component">
<template>
<paper-button raised on-click="_dialogOpen">Button</paper-button>
<paper-dialog id="dialog"><h1>Paper Dialog Here!</h1></paper-dialog>
</template>
<script>
Polymer({
is: 'poly-component',
_dialogOpen: function() {
this.$.dialog.open();
}
})
</script>
</dom-module>
First, notice how onclick changes to on-click - the Polymer event handling notation. PS. tap event is advised.
Second, you can only access other elements from code. Not directly in bindings. Hence the _dialogOpen function.
UPDATE
Ok, I know what's happening. When there is only one element with a given id, the browsers let's you use it simply by that id in global scope.
When you use Shady DOM, which I assume you do, two instances of your poly-component element render two <dialog id="dialog">. At this point window.dialog is not available anymore.
Again, with Polymer it's safer to use the this.$ notation aka Automatic node finding to reference elements in local DOM.

Call Method of Child Web Component

I'm really having difficulty trying to figure out how to call a function of a nested Polymer web component.
Here's the markup:
<rise-playlist>
<rise-playlist-item duration="5">
<rise-distribution distribution='[{"id":"VGZUDDWYAZHY"}]'></rise-distribution>
</rise-playlist-item>
</rise-playlist>
The rise-distribution component has a canPlay function that I would like to call from inside of rise-playlist.
The dom-module definition of rise-playlist looks like this:
<dom-module id="rise-playlist">
<template>
<content id="items" select="rise-playlist-item"></content>
</template>
</dom-module>
I can successfully access the rise-distribution element like this:
var distribution = Polymer.dom(this.$.items[0]).querySelector("rise-distribution");
However, when I try to call distribution.canPlay(), it says that distribution.canPlay is not a function.
I've defined the dom-module of rise-playlist-item like this:
<dom-module id="rise-playlist-item">
<content id="dist" select="rise-distribution"></content>
</dom-module>
Not sure if I need that <content> tag, although neither works.
Any ideas?
Thx.
I know that there have been a while but I am sure this problems still occurs as it is being viewed number of times.
Probably there is a problem with your component definition. Let me explain.
This is the way you put your child component inside DOM:
<your-child-component></your-child-component>
And and this should be the definition of your component:
Polymer({
is: 'your-child-component',
apiMethod: function() {
//some stuff
}
});
If you by mistake or due copy-paste error mistype the is: 'your-child-component' part, so it will not reflect the <your-child-component> you will get confused becouse your:
this.$$('your-child-component').apiMethod();
will tell you that there is no method you are willing to call.
Polymer correctly identified and selected from DOM <your-child-component> but if you have different is property (like for example is: your_child_component>) it will not attach its API to dom element you selected.
I hope that it will help if anyone ever will encounter this problem.

How to reference "this" in polymer expression

I want to pass the current polymer element as an attribute to another element. Using {{this}} returns null. Is there a supported way to access the value of "this" other than creating an attribute that returns the value
Example
<polymer-element name='my-el'>
<template>
<sub-element target={{this}}>
I think no. When a new instance of a polymer element is created, scope for template is the element instance and expressions are evaluated using this scope. So, {{this}} is evaluated using the element instance and expected to be a property on model.
"{{}}" appears to be the solution
I can't find documentation on it, but it works in v0.5 and is used in existing polymer components (core-a11y-keys)
According to the expression scopes section of the Polymer 0.5 documentation, you can use an empty binding expression: "{{}}". Note that this hasn't been documented in Polymer 1.0, so no guarantees, but it appears to still be working.
<polymer-element name="my-el">
<template>
<sub-element target="{{}}"></sub-element>
</template>
</polymer-element>
Alternatively, you can use the parentElement attribute which all polymer elements have. Here's an example from the documentation for using core-a11y-keys for keyboard navigation. Using `parentElement' would look like this:
<polymer-element name="my-el">
<template>
<sub-element target="{{parentElement}}"></sub-element>
</template>
</polymer-element>
Be careful with parentElement though. If you move the element, its parent could change.

Polymer document.querySelector not working as expected

Either I am doing something horribly wrong or Polymer just doesn't like me. See following:
<polymer-element name="menu-paper-ui" noscript>
<template>
<paper-dialog heading="Dialog" transition="paper-dialog-transition-bottom">
[ .. ]
</paper-dialog>
<paper-button label="Dialog Bottom" on-tap="{{toggleDialog}}"></paper-button>
</template>
<script>
Polymer('menu-paper-ui', {
toggleDialog : function() {
var dialog = document.querySelector('paper-dialog');
console.log(dialog); //returns null
dialog.toggle();
}
})
</script>
</polymer-element>
Now, I have my reasons to use querySelector. So, if someone can tell me whats going wrong that will be great!
This question is nearly identical to Using querySelector to find nested elements inside a Polymer template returns null.
The short answer is that elements in a polymer-element's template are put into the ShadowDOM of that element, are not not visible to the anything outside of that element. This is so that you can control styling more easily, and element IDs are scoped.
You can either give the dialog an id and use Polymer's automatic node finding, or use this.shadowRoot.querySelector('paper-dialog').
The Problem is that you can not access the shadow DOM inside a custom element with document.querySelector. See my answer to a similar question.