Please consider following example:
<script src="https://cdnjs.cloudflare.com/ajax/libs/polymer/0.5.5/polymer.js"></script>
<polymer-element name="my-outer" >
<template>
outer
<my-inner id="inner" >
<button on-click="{{buttonClick}}">push</button>
</my-inner>
outer
</template>
<script>
Polymer('my-outer', {
buttonClick: function(){
// it wasn't commented before update
//this.$.inner.buttonClick();
}
});
</script>
</polymer-element>
<polymer-element name="my-inner">
<template>
<content></content>
</template>
<script>
Polymer('my-inner', {
// update
domReady: function() {
this.eventController = this;
},
//end update
buttonClick: function(){
alert('inner');
}
});
</script>
</polymer-element>
<my-outer></my-outer>
The question is if there is any way to call Inner's buttonClick without explicit delegation in outer (putting $.inner... into on-click also doesn't work)? Maybe with bind or something.
Best reagrds, Eugene.
ps: the snippet works only in chrome. Not sure if it's polymer or stackoverflow to blame.
UPDATE: looks like putting
domReady: function() {
this.eventController = this;
},
into inner component solves the problem. But I still don't fully undestand what that eventController is. When event handler is looking for one it just iterates through node parents and picks up any with defined eventController, if none is found then node.host is used. The only other place where eventController pops up in polymer code is some lightFromTemplate function with murky comment and TODO on it.Then there is also bug https://github.com/Polymer/polymer/issues/1170 and couple of posts which do not make the issue clear for me.
So the updated question is:
What is polymer's eventController and are there any ways to work with it?
It is possible using data-binding, but this solution is not elegant. I'd much more prefer your initial solution.
<script src="https://cdnjs.cloudflare.com/ajax/libs/polymer/0.5.5/polymer.js"></script>
<polymer-element name="my-outer">
<template>
outer
<my-inner id="inner" clicked="{{clicked}}">
<button on-tap="{{click}}">push</button>
</my-inner>
outer
</template>
<script>
Polymer({
clicked: false,
click: function() {
this.clicked = !this.clicked;
}
});
</script>
</polymer-element>
<polymer-element name="my-inner">
<template>
<content></content>
</template>
<script>
Polymer('my-inner', {
publish: {
clicked: {
value: false,
reflect: true
}
},
clickedChanged: function() {
alert('inner');
}
});
</script>
</polymer-element>
<my-outer></my-outer>
Related
I am having issues accessing a method inside a dom in the callback of a node that I've attached a click listener to and I can't figure out why. I have tried the followings.
Here's the piece of code responsible to accessing the method inside callback:
<dom-module id="my-view2">
<template>
...html codes ...
</template>
<script>
Polymer({
is: 'my-view2',
... properties, etc ...
//******* trying to access a method *******************
handleClick: function(e) {
var btn = document.createElement("paper-button");
btn.addEventListener("click", function() {
var el = Polymer.dom(this).querySelector('#my-view2');
el.methodToAccess();
});
}
methodToAccess: function() {
console.log('success');
},
});
I have tried all of these:
this.$$('#my-view2")
document.querySelector("#my-view2");
Polymer.dom(this.root).querySelector('#my-view2');
Polymer.dom(this).querySelector('#my-view2');
this.getElementById('my-view2');
none of them works and all result in Cannot read property 'methodToAccess' of null. What am I doing wrong?
If you bind the callback function to the current this scope, you will have direct access to methodToAccess.
handleClick: function(e) {
var btn = document.createElement("paper-button");
btn.addEventListener("click", function() {
this.methodToAccess();
}.bind(this));
}
That being said you may want to do it the polymer way using imperative add/remove listeners:
this.listen(this.$.myButton, 'tap', 'onTap');
this.unlisten(this.$.myButton, 'tap', 'onTap');
HTH
How can I pass parameters to an annotated event listener?
I have this code:
<paper-button id="bt_close" raised on-tap="close">
Close first movement
</paper-button>
And I´m trying to call my close function with some argument (i.e., on-tap="close(1)" or close(2) or close(custom_parameter), and so on).
My close function is:
close: function (p) {
console.log(p);
}
But I´m seeing this error in the console:
listener method close(1) not defined
The event annotation requires the name of a method in your Polymer object definition. At runtime, Polymer looks up the method by name verbatim on the object, so including parameters in the method name would cause the lookup to fail, and you'd see the console error you've mentioned.
To specify an argument, you could use use a data attribute like this:
// template
<paper-button on-tap="close" data-foo="1">Close</paper-button>
// script
Polymer({
_close: function(e) {
const foo = e.target.dataset.foo;
// do something with foo
}
...
});
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
_close: function(e) {
const foo = e.target.dataset.foo;
console.log('foo', foo);
}
});
});
<head>
<base href="https://cdn.rawgit.com/download/polymer-cdn/1.8.0/lib/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="paper-button/paper-button.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<paper-button on-tap="_close" data-foo="1">Close</paper-button>
</template>
</dom-module>
</body>
codepen
Client-side click sendlogmessage calls the event, but the method inside the server-side program does not call sendlogmessage.
console.log didn't work. Can anyone help me finding the answer?
if (Meteor.isClient) {
Template.mytemplate.events({
"click": function () {
Meteor.call('sendLogMessage');
}
})
}
if (Meteor.isServer) {
Meteor.methods({
'sendLogMessage': function(){
console.log("Hello world");
}
});
}
You code is working. You just have to specify the element you are clicking on that should trigger the event. Something like this:
HTML
<template name="mytemplate">
<p id="clicable">Click me!</p>
</template>
JAVASCRIPT
Template.mytemplate.events({
"click #clicable": function() {
Meteor.call('sendLogMessage');
}
})
or
HTML
<template name="mytemplate">
<p class="clicable">Click me!</p>
</template>
JAVASCRIPT
Template.mytemplate.events({
"click .clicable": function() {
Meteor.call('sendLogMessage');
}
})
Polymer v1.2.3
I am running into an issue with Polymer and I'm not sure if its a bug or not.
I have this property that I need to set to null after doing something with it in the ready call back, however it seems like when I am initializing the property via data binding, the property gets re-initialized after I set it to null.
Take the following example:
proxy-elm.html
<dom-module id="proxy-elm">
<template>
<x-foo it="[[prox]]"></x-foo>
</template>
<script>
Polymer({
is: 'proxy-elm',
properties: {
prox: String
}
});
</script>
</dom-module>
x-foo.html
<dom-module id="x-foo">
<template>
<div>...</div>
</template>
<script>
Polymer({
is: 'x-foo',
properties: {
it: String
},
ready: function () {
//some processing stuff
console.log(this.it);
this.it = '';
setTimeout(function () {
console.log("later -- " + this.it);
}.bind(this), 3000);
}
});
</script>
</dom-module>
Main.html
<proxy-elm prox="hi"></proxy-elm>
Console
=>hi
=>
=>later -- hi
This issue only occurs then the proxy element uses data binding. If I have the proxy element set it to an immediate, the console looks like:
=>hi
=>
=> later --
Which is the desired behavior.
What's up with this? I'm going mad!
This is probably due to the initialization order (cf. Documentation)
You can try in the ready() function from your proxy to set the value of x-foo as desired like this:
<dom-module id="proxy-elm">
<template>
<x-foo id="xFoo" it="[[prox]]"></x-foo>
</template>
<script>
Polymer({
is: 'proxy-elm',
properties: {
prox: String
},
ready: function () {
this.$.xFoo.it = '';
}
});
</script>
</dom-module>
and keep the ready() function of x-foo for your specific processing!
This is indeed confusing. However, when reading the documentation very carefully, I noticed that it only mentions local dom.
It is called after the element’s template has been stamped and all elements inside the element’s local DOM have been configured (with values bound from parents, deserialized attributes, or else default values) and had their ready method called.
So the local children of your element are guaranteed to have been initialized, but not necessarily the attributes of your element.
I noticed that wrapping the code in an async helps.
ready: function () {
//some processing stuff
console.log(this.it);
this.async(function(){
this.it = '';
});
setTimeout(function () {
console.log("later -- " + this.it);
}.bind(this), 3000);
}
I'm encountering an issue binding an object that contains a function from angular to Polymer 1.0. The function is not being passed through into the target object in the custom element. Here is a simplified code sample:
The custom element has a single property named myprop:
<script>
Polymer({
is: 'my-custom-element',
properties: {
myprop: Object
},
attached: function () {
var x = this.myprop.x; //this is ok
this.myprop.myfunc(); //myfunc is not defined!
}
});
</script>
Here is the HTML:
<div ng-app="myApp">
<div ng-controller="myCtrl">
<my-custom-element myprop="{{myobject}}"></my-custom-element>
</div>
</div>
And here is the angular controller:
<script>
angular.module("myApp", []).controller("myCtrl", function ($scope) {
$scope.myobject= {
x: 4,
myfunc: function() {
//function body
}
}
});
</script>
Why isn't the function available in the custom element?
As documented here: https://github.com/Polymer/polymer/blob/3e96425bf0e0ba49b5f1f2fd2b6008e45a206692/PRIMER.md#attribute-deserialization
... objects passed into polymer elements are being passed through JSON.stringify and then JSON.parse (depending on variable type).
Functions will be completely stripped out by JSON.stringify - just checkout out this sample...
console.log( JSON.stringify({x:123,y:function(){ return 123; }}) );
// outputs: {"x":123}
I believe this is the offending line in source...
https://github.com/Polymer/polymer/blob/3b0d10b4da804703d493da7bd0b5c22fc6f7b173/src/micro/attributes.html#L232
... and comments nearby suggest possibility to change this behavior...
Users may override this method on Polymer element prototypes to provide serialization for custom types
You can't call Angular function like you write this.myprop.myfunc();
I can't explain why this is so, but if you want call Angular function from Polymer you can use this.fire('nameEvent') and in Angular controller or run module add event listener like
document.addEventListener('nameEvent', function() {
//function body
})
I hope that help you. Good luck
I'm not simulating with Angular but I think that {{myobject}} can have a problem. Only with Polymer works fine.
Basically I copied your code in the my-element and created my-element-two where I import the it. The result is "My name" printed in the lifecycle attached.
<link rel="import" href="../polymer/polymer.html">
<dom-module id="my-element">
<script>
Polymer({
is: 'my-element',
properties: {
myprop: Object,
},
attached: function () {
var x = this.myprop.x; //this is ok
this.myprop.myfunc(); //myfunc is not defined!
}
});
</script>
</dom-module>
<dom-module id="my-element-two">
<template>
<my-element myprop="{{myobject}}"></my-element>
</template>
<script>
Polymer({
is: 'my-element-two',
properties: {
myobject: {
type: Object,
value: {
x: 4,
myfunc: function() {
console.log("My name");
}
}
}
},
});
</script>
</dom-module>
<!-- results is print "My name" in the console. -->
<my-element-two></my-element-two>