How do I refresh bound data in the order-items-list element from the post-card element?
I'm using Polymer (the polymer-elements are in the shadow DOM).
I've been trying to figure this out for hours, but to no avail (I'm new to web development). One of the thing I tried is this: (givers error: Cannot read property 'getElementsByTagName' of undefined)
this.$.orderitemstemplateparent.getElementsByTagName('template')[0].iterator_.updateIteratedValue();
I have the following 3 files:
index.html:
<html>
<body unresolved>
<core-header-panel>
<div id="container">
<div id="order-items-div>
<order-items-list id="order-items-list">
order-items-list.html:
<polymer-element name="order-items-list">
<template>
<div id="orderitemstemplateparent">
<template id="order-items-template" repeat="{{post in posts}}>
<script>
Polymer ({
// FUNCTIONS THAT UPDATE THE DATA {{posts}} HERE
});
</script>
post-card.html:
<polymer-element name="post-card">
<template id="card-template">
<div id="card-header">
<paper-ripple on-tap="{{cardClick}}"></paper-ripple>
<script>
Polymer ({
cardClick: function(event, detail, sender) {
// RELOAD #order-items-template FROM HERE
}
});
</script>
Any help would be appreciated.
When you have properties with a - in the key, you need to use bracket notation to access them.
this.$['order-items-template-parent'].getElementsByTagName('template')[0].iterator_.updateIteratedValue();
Otherwise, it's parsed like this:
this.$.order - items - template - parent.getElementsByTagName('template')[0].iterator_.updateIteratedValue();
You're doing some weird subtraction, and parent is undefined.
Related
I have a polymer app with entry point index.html . For some reason i had to use dom-repeat inside index.html itself instead of a polymer element. The code is like this
<dom-bind id="mainbody">
<template>
<app-drawer-layout>
<app-drawer slot="drawer">
<template is="dom-repeat" id="mainDemoBody">
<paper-item data-value={{item.is}} id="demoItem" on-tap="onElementSelect">
{{item.is}}
</paper-item>
</template>
</app-drawer>
<div> Main content
<div>
</app-drawer-layout>
</template>
</dom-bind>
And i have on-tap function defined in the script tag like this
<script>
function onElementSelect(e) {
console.log('here');
this.selectedElement = e.model.item;
this.elementTags = this.selectedElement.tags;
this.demoLoaded = false;
}
</script>
But i am getting following error on click of any item of dom-repeat on user interface
listener method onElementSelect not defined
Can someone help me out here, Thanks in advance.
"onElementSelect" doesn't seem to be binded with the dom-bind#mainbody.
My suggestion is to create a function that has binding with mainbody. That seemed to work for me.
Code :-
var mainbody = document.getElementById('mainbody');
mainbody.onElementSelect = function(e){
console.log('here');
this.selectedElement = e.model.item;
this.elementTags = this.selectedElement.tags;
this.demoLoaded = false;
}
Edit: Please note that the solution provided is not proper or necessary for a polymer element. This particular fix is needed in this scenario because polymer components are being used in a html file.
I'm trying to learn Polymer 2.0 but am stuck with the problem of getting an element from a different Shadow Dom. This worked in Polymer 1 but no longer in Polymer 2.0. What is the correct way of writing this? It just tells me that the targetText = Null.
Thanks for your help!
This is a MWE:
Polymer WC 1:
<dom-module id="sc-navdrawer">
<template>
<style is="custom-style">
p {
font-weight: bold;
}
.changed {
color: red;
}
</style>
<p>Some text in normal p tag</p>
<div id="test" class="htmltextcontent" inner-h-t-m-l="{{inputText}}"></div>
</template>
<script>
Polymer({
is: 'sc-navdrawer',
properties: {
inputText: {
type: String,
value: "<p>Some innerhtml text in p tags</p>"
}
}
});
</script>
</dom-module>
Polymer WC 2:
<dom-module id="sc-testpage">
<template>
<button onclick="{{changeColor}}">Click here to change color</button>
</template>
<script>
Polymer({
is: 'sc-testpage',
changeColor: function() {
var targetText = document.getElementById("test");
console.log(targetText);
targetText.classList.add("changed");
}
});
</script>
</dom-module>
Well first thing that I see is you use document.getElementById("test"); and if you say this worked you have used Shady Dom. Polymer 2 forces you to use Shadow Dom so this command should be replaced by Polymer.dom(this.root).querySelector("#test"). Because Shadow Dom encapsulates your Component you cant access its content with the document Object
But this should not fix your Problem. This Encapsulation means you canĀ“t access the Content of a WebComponent so you cannot access an element with id:xyz from another Component. Have a look at these links they will explain to you how shadowDom works:
1. https://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/
2. https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM
3. https://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/
Try using paper-input and setting it's value:
<paper-input id="test" label="input" value="{{inputText}}"></paper-input>
Then you can access the variable like this:
var targetText = this.$.inputText;
(this should work with other elements other than paper-input)
Instead of using getElementById you should be using Automatic node finding This works if your two Elements have a child parent relation to each other.
I also believe instead of using a onclick on your button in WC 2, you should be using a on-tap. This is the recommended way in the Polymer documentation.
Further on, I do not really understand why you are using two way data binding on your onclick attribute. I might be missing something but your code should work perfectly fine with a normal function call.
<dom-module id="sc-testpage">
<template>
<button on-tap="changeColor">Click here to change color</button>
</template>
<script>
Polymer({
is: 'sc-testpage',
changeColor: function() {
var targetText = this.$.sc-navdrawer.$.test;
console.log(targetText);
targetText.classList.add("changed");
}
});
</script>
</dom-module>
I am building a custom element with Polymer 1.0 and need to get the content inside the tag using javascipt without it being displayed on the page. I tried using the <content> tag and fetching it inside the javascript with a query selector. This works except it displays on the page even if I use a style="display: none;" attribute. How can I get the content inside the tag without it displaying on the page?
Not sure what exactly your use-case is, but how about simply wrapping your <content> tag with a hidden <div>?
<dom-module id="x-test">
<template>
<div hidden>
<content id="content"></content>
</div>
</template>
<script>
Polymer({
is: "x-test",
attached: function () {
// access distributed content like this
var myContent = Polymer.dom(this.$.content).getDistributedNodes();
}
});
<script>
</dom-module>
I have this code in index.html:
<core-pages selected="{{welcomPage}}">
<div class="blueBackground">
<h1>asd</h1>
<h3>asd</h3>
<paper-button on-tap="{{welcomPagePlus}}">
Keep Going
<core-icon icon="forward"></core-icon>
</paper-button>
</div>
<div>welcom 2</div>
</core-pages>
and I want to call a function when the user clicks the button. I have tried this in my app.js:
function welcomPagePlus() {
...
}
this polymer code is locate in my primary file so I can't use the Polymer({...}) function. Also the button is deep inside my shadow-dom so it looks like that is the problem. Please help me find how to call a function from the shadow-dom
You can access shadow-dom elements from the "outside" like this:
First: Give your paper-button an id-Attribute: <paper-button id="paper-button-id" ...>
var button = document.querySelector("core-pages")
.shadowRoot
.querySelector("#paper-button-id");
There is no polymer required for this code. Be aware, that the 'shadowRoot' and 'querySelector' methods may not work in every browser. There may be better solutions, using polymer-methods.
You can also do it this way. Although sometimes it's useful, I hate piercing shadow boundaries and I avoid it if I can.
Codepen example
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-pages/core-pages.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-icon/core-icon.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/paper-button/paper-button.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-icons/core-icons.html">
<paper-button>
Keep Going
<core-icon icon="forward"></core-icon>
</paper-button>
<core-pages selected="second">
<div name="first" class="blueBackground">
<h1>asd</h1>
<h3>asd</h3>
</div>
<div name="second">welcome 2</div>
</core-pages>
JavaScript in the Light DOM
document.querySelector('paper-button').addEventListener('click', function(e){
var currentPage = document.querySelector('core-pages');
currentPage.selected = currentPage.selected == 0 ? 1 : 0;
});
Please see the code here http://plnkr.co/edit/FqfkcyZSqPkA7JjMMLrb?p=preview
I am embedding a javascript object/value in html, which needs to be read by angular. It reads value in index.html, but not in partial. (_global_link is read properly, but not _global_link_partial). Is it because _global_link_partial not available at $routeChangeSuccess, if so which event I need to listen to. I could provide the value as const in module definition, or directly in controller etc, but this value is very view specific and better to maintain there.
Thanks.
error:
_global_link Object {link: "abc"} controllers.js:3
ReferenceError: _global_link_partial is not defined
code:
function Test1Ctrl($scope) {
$scope.$on('$routeChangeSuccess', function ($event, current) {
console.log('_global_link', _global_link);
console.log('_global_link_partial', _global_link_partial);
});
}
function Test2Ctrl($scope) {
$scope.$on('$routeChangeSuccess', function ($event, current) {
console.log('_global_link', _global_link);
console.log('_global_link_partial', _global_link_partial); });
}
index.html
<div class="container">
<ul>
<li>test1
<li>test2
</ul>
<div ng-view></div>
</div>
<h2>in index.html</h2>
<script>
_global_link = {link: 'abc'}
</script>
partials (test1, test2)
<h2>In test1</h2>
<script>
_global_link_partial = {link: 'link1'}
</script>
<h2>In test2</h2>
<script>
_global_link_partial = {link: 'link2'}
</script>
I short, you need to include jQuery before angular.js
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js"></script>
Take a look at #igor's answer at https://groups.google.com/forum/?fromgroups=#!topic/angular/H4haaMePJU0 :
long story short: it's because the script tag is special and angular doesn't treat it as such. if you include jquery on this page, the code should work.
When angular detects jquery, it will use it for dom manipulation and jquery is smart enough to treat the script tag as special.
Here is a plunker: http://plnkr.co/edit/UhKx8QWGTExLgdQMJuyi?p=preview
I changed your example plunker to latest version of angular.js (1.2.13) and also changed the routes a little.