I want to have a single source provide all of my data. A model if you will, and I want my elements to be able to utilize that data, but never change it (one way data-binding). How can I go about this? Should I add the data as a behavior?
I tried doing this in my document:
<script type="text/javascript" src="/data.js"></script> <!-- defines a global object named DATA -->
<my-element data="{{DATA}}"></my-element>
And this inside my-element.html
<dom-module id="my-element">
<template></template>
<script>
Polymer({
is: 'my-element',
properties: {
data: Object
},
ready: function () {
console.log(this.data);
}
});
</script>
</my-element>
but it doesn't seem to work, the value of this.data is literally "{{data}}".
I am looking for a better solution than wrapping the element declaration inside a dom-bind template
To use data binding, you either need to use it inside a polymer element, or inside a dom-bind element. See the explanation here. If you use dom-bind, it's only a case of using the js to set DATA to a property on the dom-bind template element, 'data' maybe, which would be little code.
Essentially, you can't set a global and expect data binding to know about it. You need to either tell dom-bind about it, or the element about it, by setting a property on the element, perhaps using behaviour, as you suggested, or using Mowzer's approach.
An example of using a behaviour would be:
<link rel="import" href="databehaviour.html">
<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="an-ele">
<style>
</style>
<template>
<div>{{data.sth}}</div>
</template>
<script>
Polymer({
is: "an-ele",
behaviors: [DataBehaviour]
});
</script>
</dom-module>
With the behaviour being:
<script>
DataBehaviour = {
ready: function() {
this.data = {'sth':'A thing! A glorious thing!'};
}
}
</script>
But in your case, this.data would be set to your DATA global.
Use <iron-meta> [link] or <iron-localstorage>] [link] to share variables between elements or the main document.
Related
I want to send the 'categorylist' from 'submenu-list.html' to the component 'category.html' by the onclick function 'response' using observer. how can I do it (without using local-storage)? (Kindly show by editing the code)
/* submenu-list.html */
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="submenu-list">
<template>
<paper-menu>
<paper-item><a onclick="response">My Menu Items</a></paper-item>
</paper-menu>
</template>
<script>
Polymer({
is:'submenu-list',
properties: {
categorylist: {
type: Array,
value:[]
}
},
response: function() {
}
})
</script>
</dom-module>
/* category.html */
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="category">
<template>
</template>
<script>
Polymer({
is:'category',
})
</script>
</dom-module>
well the quick answer is you can`t. At least from the information you gave. Since these components seem not to be connected somehow there is no direct way to communicate between components. Possible Solutions are you write the Information into the Local Storage but as you stated you don´t want to do that. Other solutions might be redux or a rest Service but i guess thats also not an option. The last suggestion is that these both Components are siblings? then you could just use Polymer default databinding? for instance:
<submenu-list categorylist="{{categorylist}}"></submenu-list>
<category categorylist="{{categorylist}}"></category>
and then in both components add:
categorylist: {
type: Array,
value:[],
notify:true,
observer: '_categorylistChanged'
}
Now you have to implement the _categorylistChanged function which will be called when categorylist was changed.
_categorylistChanged: function(newValue, oldValue){
//do something
}
Dont´t forget when you want to change categorylist to call
this.set('categorylist', //your new value)
Otherwise the observers won´t be triggered.
I have a trusted html file with data-bindings, which I want to include to a web component.I tried multiple ways to include the html file, but the data-binding doesn't work. I know polymer won't stamp the html, because it becomes a vulnerability for XSS attacks from untrusted sources, but I have a trusted source.
I'm already aware of 1 and 2 and tried out juicy-html, iron-ajax with inner-h-t-m-l and also the injectBoundHTML function.
Is there other way than binding everything by myself?
The file I want to include contains input fields and it is a predefined form.
You can use the Templatizer by creating a <template> manually and setting its content. The important part is that you can't just set the innerHTML
Polymer({
is: 'my-elem',
behaviors: [ Polymer.Templatizer ],
ready: function() {
var template = document.createElement('template');
// you must prepare the template content first (with bindings)
var templateContent = document.createElement('div');
templateContent.innerHTML = 'First: <span style="color: red">[[person.first]]</span> <br> Last: <span style="color: green">[[person.last]]</span>';
// and cannot simply set template's innerHTML
template.content.appendChild(templateContent);
// this will process your bindings
this.templatize(template);
var person = {
first: 'Tomasz',
last: 'Pluskiewicz'
};
var itemNode = this.stamp({ person: person });
Polymer.dom(this.root).appendChild(itemNode.root);
}
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.19/webcomponents.min.js"></script>
<link rel="import" href="https://raw.githubusercontent.com/Polymer/polymer/master/polymer.html" />
</head>
<body>
<my-elem>
</my-elem>
<dom-module id="my-elem">
<template>
</template>
</dom-module>
</body>
</html>
UPDATE: The response and error events no longer bubble. https://github.com/PolymerElements/iron-ajax/releases/tag/v1.0.5
what a pity.
Original question:
I wanted to create custom ajax component based on iron-ajax to add couple of custom headers and handlers. While custom element inheritance is not yet implemented I just added iron-ajax to my-ajax and was going to delegate all api to the iron-ajax, this worked fine with generateRequest.
But when it got to handler methods I noticed that it works without any delegation. There is no on-response handler defined in my-ajax elt but handleResponse is still invoked.
As far as I understand, this happens because Polymer.Base._addFeature._createEventHandler (polymer.html:345)
uses 'this', which is top-level elt, as 'host' for handler methods definitions.
So the question is: is it bug or feature?
The example code:
<link rel="import" href="https://raw.githubusercontent.com/Polymer/polymer/master/polymer.html">
<link rel="import" href="https://raw.githubusercontent.com/PolymerElements/iron-ajax/master/iron-ajax.html">
<dom-module id="my-ajax">
<template>
<iron-ajax
id="ironAjax"
url="http://echo.jsontest.com/key/value/otherkey/othervalue"
handle-as="json"
debounce-duration="300"
>
</iron-ajax>
</template>
<script>
Polymer({
is: "my-ajax",
generateRequest: function(){
this.$.ironAjax.generateRequest();
}
});
</script>
</dom-module>
<dom-module id="my-elt">
<template>
<button on-click="buttonClick">Button</button>
<my-ajax
id="myAjax"
on-response="handleResponse">
</my-ajax>
</template>
<script>
Polymer({
is: "my-elt",
buttonClick: function(){
this.$.myAjax.generateRequest();
},
handleResponse: function(event) {
alert('got response');
}
});
</script>
</dom-module>
<my-elt></my-elt>
Most events bubble, so you are just seeing the response event bubble out of my-ajax to the my-elt scope via the handler placed on the my-ajax instance. This happens identically to a click event bubbling from a lower scope to an upper scope.
So answer is: "feature" (of the web platform, more than Polymer itself).
I'm using a simple Polymer object with Bootstrap and I want to use the tooltip (as described here) within the Polymer object.
Let's say this is my polymer:
<link rel="import" href="../components/bower_components/polymer/polymer.html">
<polymer-element name="my-polymer">
<template>
<div data-toggle="tooltip" tooltip="with a tooltip">I am a simple Polymer</div>
</template>
<script>
Polymer({
domready: function() {
//$((this.shadowRoot || this).querySelector('[data-toggle="tooltip"]')).tooltip(); // not wotking
//$("[data-toggle='tooltip']").tooltip(); // not wotking
}
});
</script>
</polymer-element>
By design, in order to get the tooltip wotking we need to execute this command:
$("[data-toggle='tooltip']").tooltip();
But because of the shadow DOM I can't execute this command.
How can I get this code to work with the Bootstrap tooltip?
I know this doesn't answer your question directly but more giving you a "Polymer" alternative. Polymer 0.5 has a tooltip element (they look a lot like the example tooltips on the link you posted)
https://www.polymer-project.org/0.5/docs/elements/core-tooltip.html
After checking core-ajax usage in the polymer website I decided to add ajax functionality using core-ajax inside my element/widget.
test-view.html
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/core-ajax/core-ajax.html">
<polymer-element name="test-view" attributes="url">
<core-ajax id="elemAjax" url="{{url}}" handleAs="json"></core-ajax>
<template>
<div id="body"></div>
</template>
<script>
Polymer('test-view', {
ready: function() {
var ajax = this.$.elemAjax; // this line
ajax.addEventListener('core-response', function() {
console.log(this.response);
});
}
});
</script>
</polymer-element>
Unfortunately, the "ajax" variable in my script returns "undefined". How can I load ajax inside an element using core-ajax?
Side Question: Is the "id" attribute inside a polymer element only accessible inside the polymer element?
Three main problems:
The core-ajax must go inside the template, so it's part of each instance's DOM (this is why ajax was undefined).
You need the auto attribute on the core-ajax (otherwise, you must call the go() method on the core-ajax to send the request).
Your event handler uses this but is not bound to the element scope. Suggest you use event delegation instead of addEventListener.
See the new example below. The other (less important) tweaks I made:
Remove id from core-ajax, we don't need to reference it anymore.
Remove the polymer.html import, core-ajax already imports it.
Remove the test-view parameter to Polymer(), it's not necessary when defining an element inside an import.
Modified example:
<link rel="import" href="bower_components/core-ajax/core-ajax.html">
<polymer-element name="test-view" attributes="url">
<template>
<core-ajax auto url="{{url}}" handleAs="json" on-core-response="{{ajaxResponse}}"></core-ajax>
<div id="body"></div>
</template>
<script>
Polymer({
ajaxResponse: function(event, response) {
console.log(response);
}
});
</script>
</polymer-element>
Even better is to avoid events altogether and data-bind directly to the response data. Example:
<link rel="import" href="bower_components/core-ajax/core-ajax.html">
<polymer-element name="test-view" attributes="url">
<template>
<core-ajax auto url="{{url}}" handleAs="json" response="{{response}}"></core-ajax>
<div id="body"></div>
</template>
<script>
Polymer({
responseChanged: function(oldValue) {
console.log(this.response);
}
});
</script>
</polymer-element>