This is a very newbie question, but how can I reference a polymer property from Chrome's console? I know I can output (console.log) from javascript in my application with a reference to this.myProperty, but how do I get a reference to it straight from the console?
You get a reference to the element by some method, I use querySelector so if you have a paper-input with the class username-input you can do something like this
document.querySelector('paper-input.username-input').myProperty
and that would be the same as doing a this.myProperty from inside the element.
During development only I create a property on window that references my
element.
Polymer({
is: 'nav-bar',
properties: {
foo: {
type: String,
value: 'foo'
}
},
attached: function() {
// #TODO remove before merge.
window.navBar = this
}
})
And in your console:
// log property
navBar.foo
// call methods
navbar.doSomething()
to check properties or call methods on my element.
Granted, this pollutes the global scope but I do this only during development.
You can also select the element via querySelector('nav-bar') but it's tedious
to do so and you lose console autocompletion. Time is money.
Related
I have multiple elements on a page that are triggering a load of select2 to the element. I'm trying to conditionally check if the element has a certain class, and if so add the tag option; otherwise do not. I thought something like this would work, but it's not:
$('.element_to_add_select_two_on').select2({
tags:function(element) {
return (element.className === 'classname_i_am_targeting');
},
});
What am I missing here? I'm subjecting myself to the following buffoonery to get this to target and load:
$('.element_to_add_select_two_on').each((index,element) => {
let showTags = false;
if ($(element).attr('class').split(' ').includes('classname_i_am_targeting')) {
showTags = true;
}
$(element).select2({
tags:showTags,
});
});
There are a few problems with your first attempt. First, you are defining tags as a function when what you want is the result of the function, since tags needs to be defined as a boolean true or false. The other is that inside your .select2() call, you do not have access to the calling element $('.element_to_add_select_two_on') in the way that you think. It isn't an event that you are listening on, it's a function call that wants an object passed with its configuration.
You conveyed that your second method works, but it can be simplified with the jQuery hasClass() function:
$('.element_to_add_select_two_on').each((index, element) => {
$(element).select2({
tags: $(element).hasClass('classname_i_am_targeting'),
});
});
There is a much simpler way to do all of this, however, and it is much more flexible and already built into select2 via the way of data-* attributes (note, you need jQuery > 1.x). You can simply add data-tags="true" to any of your select elements with which you want tags enabled. These will override any configuration options used when initializing select2 as well as any defaults:
<select data-tags="true">
...
</select>
I'm wondering, is there a possibility to have databindings "out of" a template? Say I have a <template/>-Tag somewhere which I put into the slot of a different component - that component stamps it to its context. Then I want to bind data from the root element to the <template/>-Tag. Also, event bindings (on-x-changed) don't work, because you can't assign a function which is defined in the hosting component. Any ideas?
Example:
... host
{{boundData}}
<binding-component>
<template>
{{boundData}}
</template>
</binding-component>
I don't see changes when I observe boundData in the hosting component. Is there a way to get around this? Or is firing a custom event my only chance?
If you are looking for binding a property outside of polymer something like from index.html you may bind value with element. an example ; index.html
<dom-bind>
<template>
<binding-component bound-data="{{boundData}}"></binding-component>
</template>
</dom-bind>
<script>
// set a value a string, Number or Object etc.
// Optionally wrap this code into a listener ie;
// window.addEventListener('load', e=> { ...below code ... })
var boundData= document.querySelector('dom-bind');
boundData = {} //
</script>
Now in your binding-component element has a property as boundData
hope its helps or provide more code to understand better.
I've made it work the way dom-if does it, too. Like in dom-if (reference), I'm creating a Templatize-instance which then uses forwardHostProp to handle the "inside"-properties
this.__ctor = Templatize.templatize(template, this, {
mutableData: true,
forwardHostProp(prop, value) {
// handling item updates, item being the only property
// from within the binding component
// everything else is automatically bound by templatize
this.set(prop, value);
this.update(this.item);
},
});
this.__instance = new this.__ctor();
this.root.appendChild(this.__instance.root);
This all happens in connectedCallback.
Because the Templatize-instance is passed this, it's bound to the current context as well.
Good luck!
This is the code snippet but I'm not able to understand how the observer method is working
static get properties() {
return {
selected: {
type: Object,
observer: '_selectedChanged'
}
};
}
_selectedChanged(selected, oldSelected) {
if (oldSelected) oldSelected.removeAttribute('selected');
if (selected) selected.setAttribute('selected', '');
}
connectedCallback() {
super.connectedCallback();
this.selected = this.firstElementChild;
}
full code: https://codelabs.developers.google.com/codelabs/polymer-2-carousel/index.html?index=..%2F..%2Findex#3
What is selected and oldselected and how can we do oldSelected.removerAttribute?
Are these objects of elements?
Please elaborate!
selected is property of element. It's value is some HTML element (in this case it's always img i think) so, in selected property there is always saved reference to img somewhere in html. When this property change, function _selectedChanged is called with 2 arguments. first argument is new image that is currently saved in selected and second argument is old image(previous value of selected).
further in tutorial you can see code
const elem = this.selected.nextElementSibling;
if (elem) {
this.selected = elem;
}
where is shown that const elem takes some html element and put it into this.selected.
So inside function _selectedChanged they removed html attribute from old image that was previously selected (so it was visible on screen) and added new html attribute to new image that should be visible on screen for now.
You can imagine that img with attribute selected is the only one that is shown on the screen at the time
I hope you understand my explanation. My english isn't 100% so if you have question, ask me and i can try to explain it more.
EDIT
Some example with binding and observer:
Let's say we have some paper-input which should show some results (articles for example) based on value of this input. So we have some HTML:
<paper-input value="{{search}}" label="Find articles"></paper-input>
this is primitive. Just some paper-input with value stored in search property. inside script tag:
Polymer({
is: 'test-el',
properties: {
search: {
type: String,
observer: "_findResults"
},
articles: {
type: Array
}
},
_findResults() {
this.set("articles", ['firstArticle', 'secondArticle', Math.random()]);
},
});
Explain: we defined property search and articles. Whenever property search changes, it calls function _findResults (because of observer). Function _findResults do only one thing. this.set("articles") is almost same as this.articles =. More about this can be found in documentation. So this.set("articles", ['firstArticle', 'secondArticle', Math.random()]); means it creates array and set it to articles property. and now, when we have some array that is changing everytime user enter some value in paper-input, we can add some HTML to show these articles:
<template is="dom-repeat" items="{{articles}}" as="item">
[[item]] <br>
</template>
I made also fiddle, so you can play with it and understand it a little bit more.
https://jsfiddle.net/2va41sy0/1/
Your question at the beginning was almost same in difference that they stored in some property reference to HTML object and not only just string. This is also about understand some basics of javascript and not polymer
I'm building a new webapp and I need to know how can I pass an object between 2 custom elements in polymer.
In the code below, I set the value of mydata in "my-child-element-1" and I need to see this value in "my-child-element-2"...I think that it's not very hard to do but i'm loosing my mind to find a good solution...
In my opinion, i should create a temporary object in "my-host-element" to share the value but i'm not convinced about this...
This is my code:
<dom-module id="my-host-element">
<template>
<my-child-element-1 mydata="{{mydata}}"></my-child-element-1>
<my-child-element-2 mydata="{{mydata}}"></my-child-element-2>
</template>
<script>
Polymer({
is: "my-host-element",
properties:
{
mydata: {
type: Object
}
}
});
</script>
</dom-module>
Thank you!!
Your example looks like it should work without the host element needing a property, if the property on the child elements are set up correctly. Remember that Polymer's data binding syntax is basically syntactic sugar around firing and handling custom events. So take a look in child element 1 and make sure that you've set the property to notify when changed. For example:
Polymer({
is: "my-child-element-1",
properties: {
mydata: {
type: Object,
notify: true // fire mydata-change CustomEvent on change
}
}
});
Yes, afaik it is correct to have the parent element act as the mediator between the children, which means it needs to have its own property even if its only used for that purpose.
I was wondering if it was possible to pass a function foo() as an attribute func="foo()" and have it called this.func() inside of the polymer element?
<foo-bar func="foo()"></foo-bar>
Polymer({
is: 'foo-bar',
properties: {
func: Object,
},
ready: function() {
this.func();
}
});
I've been trying to get this working for ages with no luck.
Thanks in advance.
<foo-bar func="foo()"></foo-bar>
Polymer({
is: 'foo-bar',
properties: {
func: {
type: String, // the function call is passed in as a string
notify: true
},
attached: function() {
if (this.func) {
this.callFunc = new Function('return '+ this.func);
this.callFunc(); // can now be called here or elsewhere in the Polymer object
}
});
So the trick is that "foo( )" is a string when you first pass it to the Polymer element. I fought with this for a while as well and this is the only way I could find to get it done. This solution creates a function that returns your function call, which you assign as the value of one of your polymer element properties.
Some people might say you shouldn't use the Function constructor because it is similar to eval( ) and.... well you know, the whole 'eval is evil' thing. But if you're just using it to return a call to another function and you understand the scope implications then I think this could be an appropriate use-case. If I'm wrong I'm sure someone will let us know!
Here's a link to a nice SO answer about the differences between eval( ) and the Function constructor in case it can help: https://stackoverflow.com/a/4599946/2629361
Lastly, I put this in the 'attached' lifecycle event to be on the safe side because it occurs later than 'ready'. I'm not sure if an earlier lifecycle event or 'ready' could be used instead of 'attached'. Perhaps someone can improve this answer and let us know.