Polymer app-route return empty data attributes - polymer-1.0

I'm learning Polymer and i got some issues with app-route and app-location. I tried a simple example like this:
<dom-module id="test-component">
<template>
<style scoped>
</style>
<app-location route="{{route}}" use-hash-as-path></app-location>
<app-route route="{{route}}" pattern="/test/:advisor_id/:user_id"
data="{{data}}" tail="{{subroute}}">
</app-route>
route : [[route.path]]<br>
data.advisor_id : [[data.advisor_id]]<br>
data.user_id : [[data.user_id]]
</template>
<script>
Polymer({
is: "test-component",
properties: {
route: String,
data: Object
},
ready: function() {
console.log(this.route);
}
});
</script>
</dom-module>
The main page only loads components and have test-component tags on the body
With the url localhost/test/advisor_id/14152, i see the component but data.advisor_id and data.user_id are empty. I tested route.path and it is empty too.
It seems like i forgot something but don't understand what it is.
Thanks in advance for your time

remove the 'use-hash-as-path' from your app-location, since it expects a 'http://..../#!/path' syntax for location

Related

How to hide <img> using md-switch

angular-material newbie here. I'm trying to hide some elements in our site using a switch, as instructed by our client. This led me to angular-material's md-switch.
So I tried incorporating it like so...
<md-switch md-no-ink aria-label="switchView" ng-model="switchView">{{switchView}}</md-switch>
And called the value of the switch in my element like this:
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="switchView"/>
After testing it though, it didn't hide my <img> even though my switchView changed its value. Am I missing something here?
Other methods I've tried:
Adding ng-change to my md-switch, which called a function that would equate another variable (e.g. $scope.toggleView = $scope.switchView) with switchView's value. $scope.toggleView would then be used in my ng-hide.
ng-hide = "switchView == true".
Any advice would be very much appreciated. Thank you.
UPDATE 1: To test it, I tried hiding the <div> beside my <md-switch> and it worked perfectly. However it's still not working with my <img>.
Further checking revealed that it was inside a <nav> element. However they're both using the same controller. I wonder if that's the problem? I assumed that it shouldn't be a problem because of this.
The structure is like this:
<nav ng-controller="MainController">
<!-- other navigation elements here -->
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="switchView"/>
</nav>
<div ng-controller="MainController">
<div>Toggle Switch</div>
<md-switch md-no-ink aria-label="switchView" ng-model="switchView">{{switchView}}</md-switch>
</div>
UPDATE 2: I've added the following code in my JS file because there are plans to hide elements in other pages. It still didn't work.
$scope.onChange = function(value) {
$scope.$broadcast("view_mode", $scope.switchView);
}
$scope.$on("view_mode", function(event, switchValue) {
$scope.viewThis= switchValue;
});
My HTML now looks like this:
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="viewThis"/>
As for the controller, ngMaterial was called in a separate JS file (our main), together with all our dependencies and configs. Hence, this wasn't called inside MainController.
mainApp.js
var app = angular.module('myAppModule', [
// other references here
'ngMaterial'
]);
mySample.js
angular
.module('myAppModule')
.controller('MainController', ['$scope', function ($scope) {
// functions etc. go here
Hope this helps clear things up. Thank you.
Try something like this, its a trivial example but hope it helps. Here's a link to working codepen.
There seems to be a couple ways you could handle this according to the docs:
Angular Material- MD-Switch
function exampleController($scope) {
$scope.secondModel = false;
$scope.onChangeEvent = function(value) {
$scope.imgSource = (value) ? 'http://www.fillmurray.com/300/200' : 'http://www.fillmurray.com/g/155/300';
};
// alternatively: you could set the ternary to empty string value here.
}
angular
.module('BlankApp', ['ngMaterial'])
.controller('exampleController', exampleController);
<md-switch ng-model="switchValue" ng-change="onChangeEvent(switchValue)">
<img ng-src="{{imgSource}}" alt="" />
</md-switch>
<md-switch ng-model="secondModel">
<img src="http://www.fillmurray.com/300/200" alt="" ng-hide="secondModel" />
</md-switch>
Thank you to everyone who gave their inputs. After some research, I managed to solve this problem using factories (source).
I'm sharing my solution so that it may help others who experience the same problem.
HTML:
<nav ng-controller="MainController">
<!-- other navigation elements here -->
<img ng-src="{{photoPath}}" class="profilePic" ng-hide="switchView"/>
</nav>
<div ng-controller="MainController">
<div>Toggle Switch</div>
<md-switch md-no-ink aria-label="switchView" ng-model="switchView" ng-change="onChange(switchView)">{{switchView}}</md-switch>
</div>
JS:
angular
.module('myAppModule')
.controller('MainController', ['$scope', 'ViewModeFactory', function ($scope, ViewModeFactory) {
// functions etc. go here
// For client presentation mode
$scope.onChange = function(value) {
ViewModeFactory.setViewMode($scope.switchView);
}
$scope.$watch(function (){
$scope.switchView = ViewModeFactory.getViewMode();
});
}])
.factory('ViewModeFactory', function () {
var data = {isViewMode: ''};
return {
getViewMode: function () {
return data.isViewMode;
},
setViewMode: function(value) {
data.isViewMode = value;
}
};
});
I used factories so that other controllers in our site can use the value passed by md-switch.
Hope this helps.

Error referencing dom node in expression angular

I am pulling xml into an angular app using x2js. I want to mix html into the content of certain elements, but this is making it difficult to pull that data back out for display. Here is an example of the xml.
<data>
<title>Some title here</title>
<desc>This is my <b>description</b></desc>
</data>
Using x2js I get this object
{"data": {
"title": "Some title here",
"desc": {
"b": "description",
"__text": "This is my"
}
}}
Since I can't use desc as is, I decided to write some code to work around it.
$scope.getText = function(csspath) {
return $($scope.rawXmlData).find(csspath);
}
Finally I bound the object to the scope and made my angular code do this.
<h1 ng-bind="data.title"></h1>
<p ng-bind-html="getText('data > title')"></p>
Angular responded by getting furious and told me this.
Error: $parse:isecdom
Referencing a DOM node in Expression
Is there a better way to achieve my goal? (besides switching to markdown since the client wants html sigh)
Not entirely sure why you are getting that error. However, by default angular will not allow you to print any html-string. You will have to "approve" your html by using $sce.trustAsHtml method.
Example
angular
.module('app', [])
.run(function($rootScope, $sce) {
$rootScope.getHtml = function(html) {
return $sce.trustAsHtml(html)
}
})
HTML
<!-- will not work -->
<p ng-bind-html="'<h1>a222sd</h1>'"></p>
<!-- will work as it is ran through $sce.trustAsHtml -->
<p ng-bind-html="getHtml('<h1>asd</h1>')"></p>
Live example http://jsbin.com/keraqazapo/edit?html,js,output.
UPDATE
Well, the error is below. ng-bind-html does only take a html-string to render. What you are doing here is that you, by jquery, return a dom element. Which is not allowed.
$scope.getText = function(csspath) {
//Returns dom element
//should return value of $sce.trustAsHtml
return $($scope.rawXmlData).find(csspath);
}

Polymer 1: How can I set up paper-checkbox label dynamically using a custom element

I want to set label/s of paper-checkbox elements through a custom element I have created.
This is how I am calling my custom element with the value set to a property called optionLabel which I want to display when checkbox renders on the screen.
<check-list optionLabel="My first checkbox"></check-list>
My custom element check-list looks like this:
<dom-module id="check-list">
<template>
<style>
:host {
display: block;
}
</style>
<paper-checkbox on-change="_checkChanged">{{optionLabel}}</paper-checkbox>
</template>
<script>
(function () {
'use strict';
Polymer({
is: 'check-list',
properties: {
optionLabel: {
type: String,
notify: true
}
},
_checkChanged: function (e) {
alert("State changed");
}
});
})();
</script>
</dom-module>
My goal is to reuse my custom element inside a dom-repeat layout and set values according to the requirement.
What is the correct way of doing this?
According to the documentation camelCase properties are "accessed" from outside the element like camel-case. The documentation states the following:
Attribute names with dashes are converted to camelCase property names
by capitalizing the character following each dash, then removing the
dashes. For example, the attribute first-name maps to firstName. The same mappings happen in reverse when converting property names to attribute names.
In other words, your code should have worked if you did the following instead:
<check-list option-label="My first checkbox"></check-list>
I got it to work! The variable (property) I was using previously was optionLabel, which did not work. Don't know what is the reason but when I changed it to optionlabel, i.e. all lowercase, it worked fine!
Not sure if above is the true solution to the problem I faced but it is working for me now :)
However, it will still be very helpful for many beginners like me if somebody please explain why optionLabel did not work.
So my code now changes to this
Custom element:
<dom-module id="check-list">
<template>
<style>
:host {
display: block;
}
</style>
<paper-checkbox on-change="_checkChanged">{{optionlabel}}</paper-checkbox>
</template>
<script>
(function () {
'use strict';
Polymer({
is: 'check-list',
properties: {
optionlabel: {
type: String,
notify: true
}
},
_checkChanged: function (e) {
if (e.target.checked) {
this.optionlabel = "Good to see you agree";
this.$.btnsubmit.disabled = false;
} else {
this.optionlabel = "Please agree to proceed";
this.$.btnsubmit.disabled = true;
}
}
});
})();
</script>
</dom-module>
And the call looks like:
<check-list optionlabel="My first checkbox"></check-list>

Parse Backbone.js Handlebars [Object object]

Rather new to handlbars.js but my #each is functional until I try to access a nested attribute. Specifically author.name
<!-- Handlebars.js Blog Template -->
<script id="posts-tpl" type="text/x-handlebars-template">
{{#each post}}
<div class="blog-post">
<h2 class="blog-post-title">{{title}}</h2>
<p class="blog-post-meta">{{author.name}}</p>
<div>{{{body}}}</div>
</div>
{{/each}}
</script>
Chrome Javascript console shows author as having attribute 'name' with the correct data.
The Backbone.js view appears to be working also:
var PostsView = Parse.View.extend({
template: Handlebars.compile($('#posts-tpl').html()),
render: function(){
var collection = { post: this.collection.toJSON() };
this.$el.html(this.template(collection));
}
I have a full example at http://picze.co/blog
If you take a look at what you're passing into the template, you'll see the issue.
In your render function, try inspecting what this.collection.toJSON(); actually is.
Basically, it looks something like this:
[
{
author: {
__type: "pointer",
className: "_User",
objectId: "JCAjG1AIN0"
},
title: "WTFBBQ",
body: "<p><h3>test</h3> egg on face. This cannot be good. </p>"
}
]
Looks like the author is missing the name attribute
EDIT
Seems like the name attribute exists in the model but it's nested as another model so when you call .toJSON() you won't get it.
One way would be to include the author model as well:
var collection = { post: this.collection.toJSON() };
for (var i=0; i<collection.post.length; i++) {
if (collection.post[i].author) {
collection.post[i].author = this.collection.at(i).get('author').toJSON();
}
}
I'm not familiar with parse.js so this may not be the best solution, but it should work

underscore template is removed from the DOM so can't be re-used

I'm trying to use a simple inline underscore.js template with backbone, and pulling the template from a <script> tag via jQuery's html() method.
The page is supposed to render multiple Recipe callouts for each returned by the Recipe Model. It works on the first thumbnail, but on the second, it seems the <script> tag has been removed from the DOM, so underscore fails to render it and bails with str is null on line 913
For the template, I have
<script type="text/html" id="user-recipe-rated-template">
<div class="user-recipe-rated">
<a class="thumb" href="<%= href %>"></a>
<p><%= title %></p>
</div>
</script>
And the backbone view looks like:
var UserRecipeView = Backbone.View.extend({
initialize : function() {
this.template = _.template($("#user-recipe-rated-template").html());
},
render : function()
{
this.el = this.template({
title: this.model.get("Title"),
href: '#'+this.model.get('UserContentId'),
image_src: this.model.get('ThumbnailSrc')
});
return this;
}
});
So, what I am seeing is that $("#user-recipe-rated-template") exists on the first thumbnail and all is well. On the second, it returns an empty array and underscore can't proceed.
I've trying memoizing the string of html and such, and that might work, but it seems there should be a cleaner way of doing this. What am I doing wrong?
(I'd like to use templates inlined as opposed to external JST for now to keep things simple - it seems nicer to have the template embedded in the page near where it will be loaded when the data comes in)

Resources