Listener method not defined - polymer

I'm a little new to Polymer and don't quite get what's happening here. I'm trying to create a simple form page. This is the code:
<dom-module id="sams-add-student">
<template >
<div class="vertical-section">
<paper-button on-click="addstudent">SUBMIT</paper-button>
</div>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'sams-add-student',
properties: {
item: {
type: Object
},
addstudent: function (event) {
console.log('addstudent');
}
}
});
})();
</script>
</dom-module>
However, I get an error that the listener method is not defined. Am I missing something?

You've incorrectly declared the addstudent method inside properties when it should actually be outside properties at the top-level of the object.
Polymer({
is: 'sams-add-student',
properties: {
// addstudent: function() {...} // DON'T DO THIS HERE
},
addstudent: function() {...} // DO THIS HERE
}
codepen

If it is a paper input, you could use something like :
this.$.IDofyourelement.value;

Related

Cannot render reCaptcha module more than once on my Polymer app: Uncaught Error: reCAPTCHA has already been rendered in this element

Having trouble with a reCaptcha module in a Polymer 1 app.
I can use this module once (on the register form) but if I try to use it on any other component results in an error: Uncaught Error: reCAPTCHA has already been rendered in this element.
Initially thought the problem was because I loaded the recaptcha script inside the module so I moved that to index.html. But the problem continues to persist.
Tried using grecaptcha.reset() in various places to unload the widget so it can be rendered in other components.
Inside recaptcha-module-html:
<dom-module id="recaptcha-module">
<template>
<div class="captcha-container">
<div id="captcha"></div>
</div>
</template>
<script>
Polymer({
is: "recaptcha-module",
ready: function () {
this.recaptchaCallback = this.recaptchaCallback.bind(this)
this.recaptchaExpired = this.recaptchaExpired.bind(this)
window.recaptchaCallback = this.recaptchaCallback
window.recaptchaExpired = this.recaptchaExpired
},
attached: function () {
grecaptcha.render('captcha', {
'sitekey': {SITE_KEY_HERE}
'size': 'compact',
'callback': 'recaptchaCallback',
'expired-callback': 'recaptchaExpired'
});
},
recaptchaCallback: function () {
this.fire('recaptcha-success')
},
recaptchaExpired: function () {
this.fire('recaptcha-expired')
}
});
</script>
</dom-module>
Loading the recaptcha script in index.html:
<script src="https://www.google.com/recaptcha/api.js">
</script>
How I try to load the recaptcha-module in other components:
<link rel="import" href="recaptcha-module.html">
...
<recaptcha-module></recaptcha-module>
I expect that the module can be imported and used in multiple form components with but doing so causes an error and the widget refuses to be loaded more than once.
This issue was caused because the module did not assign a unique ID to the placeholder reCaptcha element. In order to fix the issue I created a property called elementid that could be used to give each render of the reCaptcha element a unique ID.
<dom-module id="recaptcha-module">
<template>
<div class="captcha-container">
<div class="captcha" id="[[elementid]]"></div>
</div>
</template>
<script>
Polymer({
is: "recaptcha-module",
properties: {
elementid : String,
captchastyle : String
},
ready: function () {
this.recaptchaCallback = this.recaptchaCallback.bind(this)
this.recaptchaExpired = this.recaptchaExpired.bind(this)
window.recaptchaCallback = this.recaptchaCallback
window.recaptchaExpired = this.recaptchaExpired
},
attached: function () {
grecaptcha.render(this.elementid, {
'sitekey': {MY_SITE_KEY},
'size': this.captchastyle,
'callback': 'recaptchaCallback',
'expired-callback': 'recaptchaExpired'
});
},
recaptchaCallback: function () {
this.fire('recaptcha-success')
},
recaptchaExpired: function () {
this.fire('recaptcha-expired')
}
});
</script>
</dom-module>
Then you can import the module and use the custom element anywhere else by giving it a unique ID. Like so:
<recaptcha-module elementid="UNIQUE_ID" captchastyle="normal"></recaptcha-module>

Polymer data-binding not updated on array mutation

I noticed that template/data-binding in Polymer doesn't seem to reflect when a array property is mutated (i.e. push()). Sample code below:
<body>
<dom-module id="my-element">
<template>
<pre>
[my-element]
myArray: [[jsonStringify(myArray)]]
</pre>
</template>
</dom-module>
<my-element id="elm"></my-element>
<button onclick="pushArray()">pushArray</button>
<button onclick="setArray()">setArray</button>
<script>
(function registerElements() {
Polymer({
is: 'my-element',
properties: {
myArray: {
type: Array,
value: function () {
return [];
}
}
},
pushArray: function(value) {
this.push('myArray', {id: value});
},
setArray: function(value) {
this.set('myArray', [{id: value}]);
},
jsonStringify: function(obj) {
return JSON.stringify(obj);
}
});
})();
function pushArray () {
var elm = document.querySelector('#elm');
elm.pushArray('Push');
}
function setArray () {
var elm = document.querySelector('#elm');
elm.setArray('Set');
}
</script>
</body>
Whenever I click the pushArray button, an item "Push" should be added in myArray, but it wasn't reflected in the template [[jsonStringify(myArray)]]. is this an expected behavior? Anyway to work around this?
The Array change observer is a bit tricky. In your code, by using myArray, you implicitly observe (only) the reference for the (whole) array, which only changes when you run setArray.
In order to overcome this, you must also use a deep observer, namely myArray.*. The correct code for your dom-module is therefore the following:
<dom-module id="my-element">
<template>
<pre>
[my-element]
myArray: [[jsonStringify(myArray, myArray.*)]]
</pre>
</template>
</dom-module>
Live demo: http://jsbin.com/yulivuwufu/1/edit?html,css,output
No other code changes are necessary.

Polymer data from router to dom-element

I started with polymer 1.0 and created a new route endpoint as mentioned below.
page('/users/:name', scrollToTop, function(data) {
app.route = 'user-info';
app.params = data.params;
});
so if I go to users/bob it will go to route "user-info"
in my index.html the route is defined as below
<section data-route="user-info">
<web-homepage></web-homepage>
</section>
where web-homepage is a custom element.
the custom element is as defined below
<dom-module id="web-homepage">
<template>
This is homepage
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'web-homepage',
ready:function() {
//want to get the route parameters (eg: bob) here
}
});
})();
</script>
</dom-module>
Is there a way to get the value route parameter ":name" i.e bob inside the ready function?
ready function is executed when the element is imported and created. If you access route params there, it will most likely be null/empty/undefined.
However you can pass route params to the element as below.
The params in app.params is the property of app. You can simply pass it to its child elements.
index.html should look like this
<section data-route="user-info">
<web-homepage route-params=[[params]]></web-homepage>
</section>
Define the route-params in web-homepage
<dom-module id="web-homepage">
<template>
This is homepage
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'web-homepage',
properties: {
routeParams: {
type: Object,
observer: '_routeParamsChanged'
}
},
ready:function() {
//ready function is run during element creation. route-params will most likely be empty/null/undefined
//Just random
//want to get the route parameters (eg: bob) here
},
_routeParamsChanged: function(newValue) {
console.log('route params: ', newValue);
}
});
})();
</script>
</dom-module>

Change google-map center using Polymer

I'm working on a custom element using Polymer. I want to change its center after it was rendered. I can't found it on Polymer docs. Anyone could help me?
<dom-module id="my-map">
<template>
<google-map latitude="{{latitude}}" longitude="{{longitude}}" zoom="15">
</google-map>
</template>
<script>
Polymer({
is: "my-map"
// I want to change map center here
});
// or here.. I don't know
</script>
In your <script> tag you can create a ready call back function. See lifecycle callbacks
Polymer adds an extra callback, ready, which is invoked when Polymer has finished creating and initializing the element’s local DOM.
In here you can change the longitude and latitude properties of your my-map element which you are passing into the google-map element:
<dom-module id="my-map">
<style>
google-map {
height: 600px;
width: 600px;
}
</style>
<template>
<google-map latitude="{{latitude}}" longitude="{{longitude}}" zoom="15"></google-map>
</template>
</dom-module>
<script>
Polymer({
is: "my-map",
ready: function () {
this.latitude = 37.77493;
this.longitude = -122.41942;
}
});
</script>
Alternatively, if you can give the longitude and lattitude properties default values (see here):
<script>
Polymer({
is: "my-map",
properties: {
longitude: {
type: Number,
value: -122.41942
},
latitude: {
type: Number,
value: 37.77493
}
}
});
</script>

Polymer 1.0: how to access a property value inside a function

How can I access the value of a property inside a function?
Here is the property
properties:{
name: {type: String}
}
<my-element name="Subrata"></my-element>
Inside <my-element> I have a function like this:
Approach #1
<dom-module id="my-element">
<template>
...
...
</template>
<script>
(function () {
is: 'my-element',
properties:{
name: {type: String}
},
getMyName: function(){
return this.name;
}
})();
</script>
</dom-module>
My another approach was to put the value inside an element but that did not work either.
Approach #2
<dom-module id="my-element">
<template>
<!-- value of name is rendered OK on the page -->
<p id="maxp">{{name}}</p>
</template>
<script>
(function() {
is: 'my-element',
properties: {
name: {type: String}
},
getMyName: function(){
var maxpValue = this.$$("#maxp").innerHTML;
return maxpValue;
}
})();
</script>
</dom-module>
How can I accomplish this? Please help.
Thanks in advance
Instead of using a self-invoking anonymous function, you should be using the Polymer function. Change (function() { ... })(); in your code to read Polymer({ ... });.
Here's an example:
<dom-module id="my-element">
<template>
...
</template>
</dom-module>
<script>
Polymer({
is: 'my-element',
properties: {
name: {
type: String
}
},
getMyName: function() {
return this.name;
}
});
</script>
I suggest that you follow the Getting Started guide from the Polymer documentation as it goes over all of this and more. It is a good starting point when you are looking to begin working with Polymer.
You could simple do
this.name
Anywhere in any function to access the variable