Control a paper-checkbox's state - polymer

I'm trying to setup an element with a paper-checkbox inside of it. I want the checkbox's checked state to be controlled by the response of an ajax call.
HTML:
<epic-list-episode checked="<%= episode.seen? %>">
<p><strong><%= episode.show.name %></strong></p>
</epic-list-episode>
Custom element:
<polymer-element name="epic-list-episode" attributes="checked">
<template>
<link rel="stylesheet" href="epic-list-episode.css.scss" />
<div horizontal layout center>
<div flex>
<content></content>
</div>
<div vertical layout>
<paper-checkbox checked?="{{checked === 'true'}}" on-change="{{changeHandler}}"></paper-checkbox>
</div>
</div>
</template>
<script>
Polymer({
changeHandler: function(event) {
//Send ajax, wait for error/success callback
//checkbox.checked = response from ajax
}
});
</script>
</polymer-element>
How can this be achieved? I've tried return false but the checkbox still does its toggle animation.
To clarify, here is the flow i want:
Checkbox is unchecked
I click the checkbox (I don't want it to toggle yet)
Ajax request is sent off
Wait for the callback
If it's successful, toggle the state of the checkbox

I don't think you need that checked attribute at all.
What you can do is, when the on-change is called, set the checked property of the paper-checkbox back to its previous value. And then after the ajax callback, set it back to what it should be.
changeHandler: function (event, detail, sender) {
this.$.checkbox.checked = !this.$.checkbox.checked;
// give the checkbox a little loading animation
var loading = new CoreAnimation();
loading.duration = 750;
loading.easing = 'ease-in';
loading.keyframes = [{ opacity: 1, transform: "scale(1)" }, { opacity: 0.4, transform: "scale(0.9)" }];
loading.direction = 'alternate';
loading.iterations = '1000';
loading.target = this.$.checkbox;
loading.play();
// give it a little delay to act like a callback
this.job('delay', function () {
// stop the animation
loading.finish();
this.$.checkbox.checked = !this.$.checkbox.checked;
}, 3000);
}
Note that I have also included some animation code to make the user feel like the paper-checkbox is doing something, for a better user experience. Please see this jsbin for a working example.

there are a few ways to actually go about it. i have made this plunker to show the 2 ways i go about doing this. http://plnkr.co/edit/xqHCSvs63u4bdFJYM6TF?p=preview
using declarative binding
<paper-checkbox checked="{{checked}}" on-change="{{changeHandler}}"></paper-checkbox>
in your script
this.checked = true;
and pure js
<paper-checkbox id="box" on-change="{{changeHandler}}"></paper-checkbox>
then in your script
var box = document.querySelector("#box");
box.checked = true;

Related

Checkbox input is selected only when clicked outside

I have an issue with HTML which is generated via the GWT framework.
It seems that the checkbox can be selected only outside of input.
<label for="gwt-id">
<input type="checkbox" id="gwt-id" />
<span class="someclass"></span>
</label>
As you can see, there is for property. When I remove it then the checkbox can't be selected at all.
I didn't copy styles, because even after removing them it does not work. Any ideas why is it happening?
You can take a look at this thread.
But it will require some code.
Something like this:
document.addEventListener("click", function(evt) {
var flyoutElement = document.getElementById('flyout-example'),
targetElement = evt.target; // clicked element
do {
if (targetElement == flyoutElement) {
// This is a click inside. Do nothing, just return.
document.getElementById("flyout-debug").textContent = "Clicked inside!";
return;
}
// Go up the DOM
targetElement = targetElement.parentNode;
} while (targetElement);
// This is a click outside.
document.getElementById("flyout-debug").textContent = "Clicked outside!";
});
If you want, you can use an external library.
Or with Vue.js and React.js

Show a div by wrap with another controller doesn't work

I have a button in a div with a controller named controllerBubble. I would like this button show a div controlled by an other controller : controllerDependance. Is it possible to wrap the button in a div and the hidden div with same controller but it doesn't works.
This is my HTML :
<div ng-app="app">
<div ng-controller="mainController" ng-show="myvalue" class="ng-cloak">
<div id="panelSap" ng-controller="controllerDependance">
My hidden div
</div>
</div>
<div id="containerDetailsTicket" class="clearfix" ng-controller="controllerBubble">
Div which contains the button
<div id="containerButton" ng-controller="mainController">
<button ng-click="showAlert()">Afficher</button>
</div>
</div>
</div>
This is my controllers :
var d3DemoApp = angular.module('app', [])
d3DemoApp.controller('controllerBubble', function() {
});
d3DemoApp.controller('controllerDependance', function($scope) {
$scope.myvalue = false;
$scope.showAlert = function() {
$scope.myvalue = true;
};
});
d3DemoApp.controller('mainController', function AppCtrl($rootScope, $scope) {
$scope.myvalue = false;
$scope.showAlert = function() {
$scope.myvalue = true;
};
});
I created a Plunker
Any idea what's happening ? Someone can do work on the Plunker. I Hope someone can help me.
Thanks a lot.
Look, not sure why you want to have such a nesting of controllers but I am pretty much sure that it ain't good. I'll tell you why. In your code, you are trying to use same controller at two DOM ele. So, they are having 2 different scope $scope and so they are not working.
I have made a working plunker for you by using $rootScopebut its not a clean approach as you'll be having a global variable ($rootScope.myvalue) declared. Declaring global variable should always be avoided unless forced to.
Another suggested approach in plunker is to use $emit as event notifier. The $on would take appropriate action when the event is triggered. You can even pass values that too to different controllers.
Service can also be used to pass values among controllers .
Let me know if you need more info
Update 1:
If you want to remove some div (not hide) then you should try to use ng-if.

Polymer paper-input-decorator updateLabelVisibility() is not working

I don't know how I am supose to use the updateLabelVisiblity() function on a paper-input-decorator element. This should work but it doesn't!
In my plunker a normal inputs value is connected to a paper-inputs value. Whenever I type something in my normal input a function is called. That function calls validate() and updateLabelVisiblity.
Here is a plunker and here is my Polymer-element.
<polymer-element name='my-input'>
<template>
<h3>Paper input (linked)</h3>
<paper-input-decorator id='myPaperInput' label='Field' error='error' floatingLabel autovalidate>
<input is='core-input' pattern='^[0-9]*$' value='{{something}}'>
</paper-input-decorator>
<h3>Normal input (linked)</h3>
<input value='{{something}}' on-keyup='{{mykeyup}}'>
<p>
Why doesn't the label show above the paper-input when i start typing in the <b>Normal Input</b>?
</p>
</template>
<script>
Polymer({
mykeyup: function(){
this.$.myPaperInput.validate();
this.$.myPaperInput.updateLabelVisibility();
}
});
</script>
</polymer-element>
Solved
mykeyup: function(){
var p = this.$.myPaperInput;
p.validate();
p._autoLabelVisible = p.querySelector('input').value !== '' ? false : true;
}
I see what's happening. The updateLabelVisibility requires the value in order to show the floating label. However instead using updateLabelVisibility you can also do this hack:
this.$.myPaperInput._autoLabelVisible = false;
Which basically just hard sets the value that updateLabelVisibility is setting.
Here is your code, just updated:
http://plnkr.co/edit/l4xQBv7PKft2zqARnPu1?p=preview
Reference:
https://github.com/Polymer/paper-input/blob/master/paper-input-decorator.html#L474

Remove child element's attribute from Polymer js

I've a custom element which, among other things, has a core-input and a paper button in it.
When the element is created, the input is disabled, and I want to enable it when I tap the button.
I've tried several ways and can't access the input's attribute.
<paper-input-decorator label="Nombre de usuario" floatingLabel>
<input id="usernameinput" value="{{UserName}}" is="core-input" disabled />
</paper-input-decorator>
<paper-button raised id="edprobutton" on-tap="{{edbutTapped}}">EDITAR</paper-button>
What should I write in
edbutTapped: function () {
},
EDIT
So, I've learned that the problem was that my username input element was inside a repeat template, and that's bad for what I was trying to do. Now I'm trying to bind a single json object to my element, with no luck so far.
What I have right now:
In my Index page:
<profile-page id="profpage" isProfile="true" entity="{{profEntity}}"></profile-page>
<script>
$(document).ready(function () {
var maintemplate = document.querySelector('#fulltemplate');
$.getJSON('api/userProfile.json', function (data) {
var jsonString = JSON.stringify(data);
alert(jsonString);
maintemplate.profEntity = jsonString;
});
}
</script>
In my element's page:
<polymer-element name="profile-page" attributes="isprofile entity">
<template>
<style>
[...]
</style>
<div flex vertical layout>
<core-label class="namepro">{{entity.Name}}</core-label>
<core-label class="subpro">{{entity.CompanyPosition}}</core-label>
<core-label class="subpro">{{entity.OrgUnitName}}</core-label>
</div>
</template>
</polymer-element>
And my JSON looks like this:
{"Name": "Sara Alvarez","CompanyPosition": "Desarrollo","OrgUnitName": "N-Adviser"}
I'm asuming I need to "update" my element somehow after changing its entity attribute?
Try the following
<script>
Polymer({
edbutTapped: function () {
this.$.usernameinput.disabled = false;
}
});
</script>
The this.$ allows you to access controls defined in an elements and the usernameinput is the id you assigned to the input.
This can go below the closing tag of the element you are defining.
'disabled' is conditional-attribute.
So this will be the correct use of it:
<input id="usernameinput" value="{{UserName}}" is="core-input" disabled?="{{isDisabled}}" />
In the prototype:
//first disable the field, can be done in ready callback:
ready: function () {
this.isDisabled = 'true';
}
//set idDisabled to 'false' i.e. enable the input
edbutTapped: function () {
this.isDisabled = 'false';
},
OK this is going to be a long answer (hence why I am not entering this as an edit of my original answer). I've just done something which is functionally the same.
The first thing is this code;
$.getJSON('api/userProfile.json', function (data) {
var jsonString = JSON.stringify(data);
alert(jsonString);
maintemplate.profEntity = jsonString;
});
Polymer has a control called core-ajax - this as it's name suggests makes an ajax call. The other really nice thing is that it can be made to execute when the URL changes. This is the code from the project I've got.
<core-ajax id="ajax"
auto=true
method="POST"
url="/RoutingMapHandler.php?Command=retrieve&Id=all"
response="{{response}}"
handleas="json"
on-core-error="{{handleError}}"
on-core-response="{{handleResponse}}">
</core-ajax>
The auto is the bit which tells it to fire when the URL changes. The description of auto from the polymer documentation is as follows;
With auto set to true, the element performs a request whenever its
url, params or body properties are changed.
you don't need the on-core-response but the on-core-error might be more useful. For my code response contains the JSON returned.
So for your code - it would be something like this
<core-ajax id="ajax"
auto=true
method="POST"
url="/api/userProfile.json"
response="{{jsonString}}"
handleas="json"
on-core-error="{{handleError}}" >
</core-ajax>
Now we have the data coming into your project we need to handle this. This is done by making use of Polymer's data-binding.
Lets detour to the element you are creating. Cannot see anything wrong with the following line.
<polymer-element name="profile-page" attributes="isprofile entity">
We have an element called 'profile-page' with two properties 'isprofile' and 'entity'.
Only because my Javascript leaves a bit to be desired I would pass each property as a seperate entity making that line
<polymer-element name="profile-page" attributes="isprofile name companyposition OrgUnitName">
Then at the bottom of your element define a script tag
<script>
Polymer({
name: "",
companyposition: "",
OrgUnitName: ""
});
</script>
Now back to the calling (profile-page). The following code (from my project) has the following;
<template repeat="{{m in response.data}}">
<map-list-element mapname="{{m.mapName}}" recordid="{{m.Id}}" on-show-settings="{{showSettings}}">
</map-list-element>
</template>
Here we repeat the following each element. In your case you only have one entry and it is stored in jsonString so your template is something like this
<template repeat="{{u in jsonString}}">
<profile-page name="{{u.name}} companyposition="{{u.companyposition}}" OrgUnitName="{{u.OrgUnitName}}">
</profile-page>
</template>
Now we get to the issue you have. Return to your profie-page element. Nothing wrong with the line
on-tap="{{edbutTapped}}"
This calls a function called edbutTapped. Taking the code I gave you earlier
<script>
Polymer({
edbutTapped: function () {
this.$.usernameinput.disabled = false;
}
});
</script>
The only thing to change here is add the following code
created: function() {
this.$.usernameinput.disabled = true;
},
This is inserted after the Polymer({ line. I cannot see in your revised code where the usernameinput is defined but I am assuming you have not posted it and it is defined in the element.
And you should be working, but remember to keep your case consistent and to be honest I've not been - certain parts of Polymer are case sensitive - that catches me out all the time :)

Polymer ondblclick not working

I am trying to use ondblclick inside polymer element, but I cannot get it to work.
I know that I can just use ondblclick="someFunction()" but I need to access double clicked element model, something like on-tap event:
event.target.templateInstance.model.myModel;
<script src="http://www.polymer-project.org/platform.js"></script>
<script src="http://www.polymer-project.org/polymer.js"></script>
<polymer-element name="dblclick-test">
<template>
<button on-dblclick="{{btnDblClick}}" on-tap="{{btnTap}}">{{btnText}}</button>
</template>
<script>
Polymer({
btnText: 'double click me',
btnDblClick: function(event) {
// in real code I need to use
// event.target.templateInstance.model
// just like on-tap's event param
this.btnText = 'Hi, u dbl clicked me !!!!!!';
},
btnTap: function(event) {
this.btnText = 'Hi, u clicked me !';
}
})
</script>
</polymer-element>
<dblclick-test></dblclick-test>
Is there any polymeric way to do it?
First
I was missing the declarative event mapping by using ondbleclick instead of on-dblclick, thanks to ebidel edit to my question.
Even though the above example won't work.
Second
To solve the conflict between on-tap and on-dblclick, I used something like the following in my code:
<script src="http://www.polymer-project.org/platform.js"></script>
<script src="http://www.polymer-project.org/polymer.js"></script>
<polymer-element name="dblclick-test">
<template>
<button on-tap="{{btnTap}}">{{btnText}}</button>
</template>
<script>
Polymer({
btnText: 'double click me',
btnDblClick: function(event) {
this.btnText = 'Hi, u dbl clicked me !!!!!!';
},
btnTap: function(event) {
if (this.tappedOneTime) {
this.btnDblClick();
this.tappedOneTime = false;
} else {
this.btnText = 'Hi, u clicked me !';
}
this.tappedOneTime = true;
// reset flag after 800ms
this.async(function() {
this.tappedOneTime = false;
}, null, 800);
}
})
</script>
</polymer-element>
<dblclick-test></dblclick-test>
I assume tap is also fired on dblclick this makes it difficult.
My (and other answers) to this question Distinguish between onClick and onDoubleClick on same element to perform different actions in Dart show possible solutions.
Don't use on-tap and on-dblclick together, if you need both behaviors use on-click instead on-tap.
<my-elem on-click="clicked" on-dblclick="dblclicked">