iron-collapse opened=false not collapsing when bound with Boolean property of object - data-binding

I have an array of objects which has a field to indicate whether its properties should be displayed:
[{
state: true
},
{
state: false
},
{
state: false
}]
And I use Polymer iron-collapse's "opened" field to bind with state in order to collapse it.
This works in Polymer 0.5, but it fails in 1.0. Also, it works if I directly pass a boolean property - just not with an object.
When I say "doesn't work", I mean that the collapsing doesn't happen.
What did I fail to migrate properly? Or is this a bug in iron-collapse?
This Works:
(Using an Array of Boolean)
demo.html:
<html>
<head>
<link rel="import" href="iron-collapse-demo.html">
</head>
<body>
<iron-collapse-demo states='[ true, false, false ]'></iron-collapse-demo>
</body>
</html>
iron-collapse-demo.html:
<html>
<head>
<script src="../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../bower_components/iron-collapse/iron-collapse.html">
</head>
<body>
<dom-module id="iron-collapse-demo">
<style>
</style>
<template>
<template is="dom-repeat" items="{{states}}">
<span on-tap="collapseToggle"><+></span>
<iron-collapse opened="{{item}}">
<div>Hello collapse!</div>
</iron-collapse>
</template>
</template>
</dom-module>
</body>
<script src="iron-collapse-demo.html.0.js"></script>
</html>
iron-collapse-demo.html.0.js:
Polymer({
'is': 'iron-collapse-demo',
'properties': {
'states': Array
},
'ready': function() {
},
'collapseToggle': function(event, detail, sender) {
event.model.item = !event.model.item;
},
});
This doesn't work:
(Using an Array of Object with a Boolean property)
demo.html
<html>
<head>
<link rel="import" href="iron-collapse-demo.html">
</head>
<body>
<iron-collapse-demo nums='[ {"state": true}, {"state": false}, {"state": false} ]'></iron-collapse-demo>
</body>
</html>
iron-collapse-demo.html:
<html>
<head>
<script src="../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../bower_components/iron-collapse/iron-collapse.html">
</head>
<body>
<dom-module id="iron-collapse-demo">
<style>
</style>
<template>
<template is="dom-repeat" items="{{nums}}">
<span on-tap="collapseToggle"><+></span>
<iron-collapse opened="{{item.state}}">
<div>Hello collapse!</div>
</iron-collapse>
</template>
</template>
</dom-module>
</body>
<script src="iron-collapse-demo.html.0.js"></script>
</html>
iron-collapse-demo.html.0.js:
Polymer({
'is': 'iron-collapse-demo',
'properties': {
'nums': Array
},
'ready': function() {
},
'collapseToggle': function(event, detail, sender) {
var num = event.model.item;
num.state = !num.state;
},
});

I found a hack/workaround, though I'm not convinced this should be the only way that works..
I wrapped the span and iron-collapse inside a div so that I can use a querySelector and toggle() the collapse.
iron-collapse-demo.html:
<template is="dom-repeat" items="{{nums}}">
<div>
<span on-tap="collapseToggle"><+></span>
<iron-collapse opened="{{item.state}}">
<div>Hello collapse!</div>
</iron-collapse>
</div>
</template>
iron-collapse-demo.html.0.js:
new collapseToggle:
'collapseToggle': function(event, detail, sender) {
// event.model.item.state = !event.model.item.state;
event.currentTarget.parentElement.querySelector('iron-collapse').toggle();
}

Try:
<iron-collapse horizontal opened$="[[item.state]]">
...
</iron-collapse>
HTML booleans are true when the attribute is present, not if the value of the attribute is true. Binding the attribute instead of value means Polymer outputs the attribute name when true but nothing for false.

Related

How to use Polymerfire to fetch data from a Firebase

Description
My goal is to use the polymerfire element to send a request to a Firebase endpoint to detect if there is data there and, if so, its content.
Please include in your answer a working demo if possible and extra points if you point to some good documentation as the current documentation is insufficient.
Expected outcome
I expect the demo page to look like:
CLICK ME
ornithischia
foo bar baz
And when the CLICK ME button is pressed, the following to appear in the console:
"You clicked me!"
"triceratops"
"{appeared: -68000000, height: 3, length: 8, order: "ornithischia", vanished: -66000000, weight: 11000}"
Actual outcome
The the demo page looks like:
CLICK ME
foo bar baz
And when the CLICK ME button is pressed, the following actually appears in the console:
"You clicked me!"
"triceratops"
"{}"
Live Demo
http://jsbin.com/fasovaxonu/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<!-- Source: https://github.com/Download/polymer-cdn -->
<base href="https://cdn.rawgit.com/download/polymer-cdn/1.7.0.2/lib/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymerfire/polymerfire.html">
<link rel="import" href="paper-button/paper-button.html">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<firebase-app name="my-app"
auth-domain="dinosaur-facts.firebaseapp.com"
database-url="https://dinosaur-facts.firebaseio.com/"
>
</firebase-app>
<p>
<paper-button on-tap="_onTap">Click Me</paper-button>
</p>
<!---->
<firebase-query
app-name="my-app"
path="https://dinosaur-facts.firebaseio.com/dinosaurs"
data="{{dinosaurs}}"
>
</firebase-query>
<firebase-document
app-name="my-app"
path="https://dinosaur-facts.firebaseio.com/dinosaurs/triceratops"
data="{{triceratops}}"
>
</firebase-document>
[[triceratops.order]]
<br /><br />
<template is="dom-repeat" items="[[dinosaurs]]">
[[item.order]]
</template>
<template is="dom-repeat" items="[[test]]">
[[item]]
</template>
<!---->
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
dinosaurs: Array,
test: {
value: function() {
return ['foo', 'bar', 'baz'];
}
},
},
_onTap: function() {
console.log('You clicked me!');
console.log('triceratops', JSON.stringify(this.triceratops));
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
You first need to include <firebase-app> to initialize firebase.
<firebase-app
database-url="dinos-89701.firebaseio.com"
api-key="AIzaSyDLkCy3RNC5uFomEjVsLUehpzKFDrfAplU"
auth-domain="dinos-89701.firebaseio.com">
</firebase-app>
Get your api-key here:
https://console.firebase.google.com/project/YOUR_PROJECT/settings/general/
Demo:
http://jsbin.com/joxatuz/1/edit?html,console,output

Firebase 2.x + Polymer 1.x: Loading Polymerfire from CDN and fetching data

I want to use the polymerfire element to fetch the data at https://dinosaur-facts.firebaseio.com/dinosaurs and display the data in a dom-repeat element.
What am I doing wrong? How do I do that correctly?
Here is the jsBin.
http://jsbin.com/zeyimotasa/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<!-- Source: https://github.com/Download/polymer-cdn -->
<base href="https://cdn.rawgit.com/download/polymer-cdn/1.7.0.2/lib/">
<!--- ->
<base href="https://polygit.org/components/">
<!--- ->
Toggle below/above as backup when server is down
<!--- ->
<base href="https://polygit2.appspot.com/components/">
<!---->
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="polymerfire/polymerfire.html" rel="import">
<link href="paper-button/paper-button.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<paper-button on-tap="_handleClick">Click Me</paper-button>
</p>
<!---->
<firebase-document
path="https://dinosaur-facts.firebaseio.com/dinosaurs"
data="{{dinosaurs}}"
>
</firebase-document>
<template is="dom-repeat" items="[[dinosaurs]]">
[[item.order]]
</template>
<template is="dom-repeat" items="[[test]]">
[[item]]
</template>
<!---->
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
dinosaurs: Array,
test: {
value: function() {
return ['foo', 'bar', 'baz'];
}
},
},
_handleClick: function() {
console.log('You clicked me!');
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
To get data in array/collection form, you need to use the <firebase-query> element, not <firebase-document>. You also need to initialize your application with <firebase-app>:
<firebase-app api-key="XXX" database-url="yyy" auth-domain="zzz"></firebase-app>
<firebase-query path="/dinosaurs" data="{{dinosaurs}}"></firebase-query>
<template is="dom-repeat" items="[[dinosaurs]]">
<!-- ... -->
</template>
You need a <firebase-app> to initialize the Firebase App, don't you?

getting undefined value in localstorage angularjs

In below ExamppleController function a value is entered into message variable local storage. For the first time value is getting stored but when entered again value is not getting stored. When browser cache is cleared then value is stored again and second time no value is getting stored.
Mystorage.html
<html>
<head>
<script src="angular.min.js"></script>
<script src="ngStorage.min.js"></script>
<script>
var example = angular.module("example", ["ngStorage"]);
example.controller("ExampleController", function($scope,$rootScope,$window,$localStorage,$location) {
$scope.save = function() {
$rootScope.newq=$scope.name;
$scope.$apply();
**$localStorage.message = $scope.name;**
console.debug($localStorage.message);
$window.location.href = 'nextstorage.html';
}
});
</script>
</head>
<body ng-app="example">
<div ng-controller="ExampleController">
<input type="text" ng-model="name"/>
<button ng-click="save()">Save</button>
<br>
{{data}}
</div>
</body>
</html>
NextStorage.html
<html>
<head>
<script src="angular.min.js"></script>
<script src="ngStorage.min.js"></script>
<script>
var example = angular.module("example", ["ngStorage"]);
example.controller("ExampleController", function($scope,$window,$localStorage,$location) {
$scope.data1 = $localStorage.message;
});
</script>
</head>
<body ng-app="example">
<div ng-controller="ExampleController">
<span>{{data1}}</span>
</div>
</body>
</html>
You should really be doing things the AngularJS way. I think this is where the disconnect happens.
See the following code:
<html>
<head>
<script src="angular.min.js"></script>
<script src="ngStorage.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.min.js"></script>
<script>
var example = angular.module("example", ["ngStorage", "ui.router"]);
example.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('1', {
url: '/1',
templateUrl: 'templates/1.html',
controller: 'FirstController'
})
.state('2', {
url: '/2',
templateUrl: 'templates/2.html',
controller: 'SecondController'
});
$urlRouterProvider.otherwise('/1');
});
example.controller("FirstController", function($scope,$localStorage,$location) {
$scope.save = function() {
$localStorage.message = $scope.name;
$location.path("/2");
}
});
example.controller("SecondController", function($scope,$localStorage,$location) {
$scope.data1 = $localStorage.message;
});
</script>
</head>
<body ng-app="example">
<div ui-view></div>
<script id="templates/1.html" type="text/ng-template">
<div>
<input type="text" ng-model="name"/>
<button ng-click="save()">Save</button>
<br>
</div>
</script>
<script id="templates/2.html" type="text/ng-template">
<div>
<span>{{data1}}</span>
</div>
</script>
</body>
</html>
You'll notice I'm using routes and navigating between them using the $location provider. The $localStorage works fine when doing it this way.
Read up on the ui-router or ngRoute.
Regards,

Style in KendoUI with AngularJS

Creating a simple KendoUI drop down list using AngularJS. Not seeing the drop down with the correct styling.
Here's the html...
<div ng-controller="welcome2 as vm">
<select kendo-drop-down-list k-options="vm.phoneOptions"></select>
</div>
The js file:
(function () {
'use strict';
angular.module('app')
.controller('welcome3',
[welcome3]);
function welcome3() {
var vm = this;
vm.activate = activate;
activate();
function activate() {
vm.phoneOptions = {
dataSource: {
data: [
{name: "iPhone"},
{name: "Droid"},
{name: "Windows"}
]
},
dataTextField: "name",
dataValueField: "id",
optionLabel: "Select a phone..."
};
}
}
})();
Inside the index.js file I have (among other things) the following:
<!DOCTYPE html>
<html ng-app="app">
<head lang="en">
<meta charset="UTF-8">
<link href="content/bootstrap.css" rel="stylesheet" />
<link href="content/kendo.common.min.css" rel="stylesheet" />
<link href="content/kendo.default.min.css" rel="stylesheet.css" />
</head>
<body>
// ...
<div ng-view></div>
<script src="scripts/jquery.min.js"></script>
<script src="scripts/angular.js"></script>
<script src="scripts/angular-route.js"></script>
<script src="scripts/kendo.all.min.js"></script>
<script src="scripts/angular-kendo.js"></script>
//....
<script src="app/welcome/welcome3.js"></script>
</body>
</html>
The drop down looks like this:
As opposed to this:
Thanks!!
Usually when you have an unstyled control like that, it's because you have a wrong stylesheet link. It looks like the common file is linked right, but check the other. Also, when using Bootstrap, make sure to use the common-bootstrap CSS file.
http://trykendoui.telerik.com/#burkeholland/UXav

jsView - How to render the content of a custom tag with its props as its data?

I have custom tag which can have itself as an inner tag and I want to bind it its props as data. I can change the first test tag title property and see the change but cannot do that for the inner test tag. I think it is because of the wrong arguments of this.tagCtx.content.render(). Below is the example:
<!DOCTYPE html>
<html>
<head>
<script src="js/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="js/jsrender.js" type="text/javascript"></script>
<script src="js/jquery.observable.js" type="text/javascript"></script>
<script src="js/jquery.views.js" type="text/javascript"></script>
<script id="testTemplate" type="text/x-jsrender">
<div>{^{>title}}{^{:content}}</div>
</script>
<script id="myTemplate" type="text/x-jsrender">
{^{test title='Test1'}}
{^{test title='Test2'}}
{{/test}}
{{/test}}
</script>
<script type="text/javascript">
$.views.tags({
test: {
render: function(){
this.tagCtx.props.content = this.tagCtx.content.render();
return this.template.render(this.tagCtx.props, this.tagCtx, this.tagCtx.view);
},
template: "#testTemplate"
}
});
$.templates({myTemplate: "#myTemplate"});
$(function () {
$.link.myTemplate('#container', {});
$('#editTitle').click(function () {
$.observable($.view('#container div:first div').data).setProperty('title', prompt());
});
});
</script>
</head>
<body>
<span id="editTitle">EditTitle</span>
<div id="container"></div>
</body>
</html>
The problem here is that the inner tag is being rendered as a string, not as a data-linked tag, since the this.tagCtx.content.render() call is simply calling the render method on the compiled template corresponding to the block content.
If you want to render as a data-linked tag, you need to call this.tagCtx.render().
In addition, in calling this.tagCtx.render() you need the tag to render its content, and not another template. Setting template: "#testTemplate" will cause the tag to use that template instead of the content. So what you need is something along these lines:
var template = $.templates("#testTemplate");
$.views.tags({
test: {
render: function() {
var tagCtx = this.tagCtx;
tagCtx.props.content = tagCtx.render();
return template.render(tagCtx.props, undefined, tagCtx.view);
}
}
});
You probably don't want to pass in tagCtx as context in the template.render(...) call. You can pass in tagCtx.ctx, or simply undefined...

Resources