dom-if issue in polymer? - javascript

I have an table element where the declaration is as follows
<euro-table id="euroTable" number-visible-rows="10">
<euro-column title="Id" type="text" key="Id"></euro-column>
<euro-column title="Descripcion" type="text" key="Descripcion"></euro-column>
<euro-column title="Abreviatura" type="text" key="ShortName"></euro-column>
<euro-column title="Tipo" type="object" key="FeeType" objectkey="Descripcion"></euro-column>
<euro-column title="Monto($)" type="text" key="Monto"></euro-column>
<euro-column title="Cobrar a" type="array" key="NivelesEscolares" objectkey="Descripcion"></euro-column>
</euro-table>
Data is added using javascript after an iron-ajax request. Everything works as it should work, except for one thing: when I use dom-repeat to bind added data I use <dom-if> template because depending on the type of column, I must access and display the corresponding information. The code I use to do that is the following:
<template is="dom-repeat" items="{{visibleRows}}" id="tableRow" as="row">
<tr on-tap="rowSelected" class$="{{getClass(item.active)}}">
<template is="dom-repeat" items="{{headers}}" id="tableRow2" as="column">
<template is="dom-if" if="{{getType(column.type, 'object')}}">
<td>
<li>{{getObjectValue(column,row)}}</li>
</td>
</template>
<template is="dom-if" if="{{getType(column.type, 'array')}}">
<td>
<template is="dom-repeat" items="{{getDataArray(column,row)}}">
<li>{{getObjectValue(column,row)}}</li>
</template>
</td>
</template>
<template is="dom-if" if="{{getType(column.type, 'text')}}">
<td>{{getValue(column,row)}}</td>
</template>
</template>
</tr>
</template>
So my problem is that I can not display the information correctly and I think the reason is for the use of dom-repeat. My information is displayed as follows:
The information is out of the table, I'm a checking my getType function but I think its ok. Any idea about to fix my bug? Thanks!

After I had researched a little more, I found here that my problem was a bug of polymer. To solve it, is necessary to change two functions in Polymer.html file. The functions are _wrapTextNodes and _showHideChildren. I will leave the functions here just in case anyone have the same problem.
_wrapTextNodes: function(root) {
// wrap text nodes in span so they can be hidden.
for (var n = root.firstChild; n; n=n.nextSibling) {
if (n.nodeType === Node.TEXT_NODE && n.textContent.trim.length) {
var s = document.createElement('span');
root.insertBefore(s, n);
s.appendChild(n);
n = s;
}
}
},
_showHideChildren: function() {
var hidden = this._hideTemplateChildren || !this.if;
if (this._instance) {
var c$ = this._instance._children;
for (var i=0; i<c$.length; i++) {
var c = c$[i];
if (c.nodeType !== Node.TEXT_NODE) {
c.style.display = hidden ? 'none' : '';
c._hideTemplateChildren = hidden;
}
}
}
},
Here you can find dom-if.html file.

Related

Vue v-text-field - previous value is automatically displayed when clicked

The Vue input fields (v-text-field) automatically show the previous input when I click on the text field.
Actually, I delete the value from all inputs with the blue button (which also creates additional random tables). The reset works, but why is the value displayed again?
What I tried: I used v-form to delete the value of all inputs with this.$refs.form.reset(); (see https://vuetifyjs.com/en/components/forms/#misc). That didn't solve the problem.
This is how it looks:
GIF
HTML
<v-simple-table>
<template v-slot:default>
...
<tbody>
<tr :class="verb.ich">
<td>
<v-text-field label="ich"></v-text-field>
</td>
</tr>
<tr :class="verb.du">
<td>
<v-text-field label="du"></v-text-field>
</td>
</tr>
<tr :class="verb.er">
<td>
<v-text-field label="er/sie/es"></v-text-field>
</td>
</tr>
...
...
</tbody>
</template>
</v-simple-table>
...
<v-btn #click="next"> Weiter </v-btn>
Method next():
next: function () {
var allInputs = document.getElementsByTagName("input");
for (var i = 0, max = allInputs.length; i < max; i++) {
allInputs[i].value = "";
allInputs[i].style.backgroundColor = "white";
}
...
}
Solution
(with the help of Michael LevĂ˝'s answer)
v-model
<td>
<v-text-field v-model="verb.val[0]"></v-text-field>
</td>
...
reset value
for (var i = 0; i < this.verben.length; i++) {
this.verben[i].val[0] = "";
...
}
in each array
verben: [
{
val: ["", "", "", "", "", ""],
...
}
v-text-field has some internal variable which saves the value when you are typing. Your next() method doesn't clear this value but only sets value of the rendered <input> control - when you click on the control, v-text-field is re-rendered and shows the value stored inside
Your next method is an example how not to work with form items in Vue. Vue is data driven. For each control you need a variable in data() section of your component and use v-model to bind the control to that variable.
Now when you want to change the value programmatically, you change the data in your component (not in the DOM)
Form Input Bindings
Vuetify form controls works same way - examples

display data in specific order in polymer

In my polymer dom, each data object todo has multiple items and it also has a todo.idx. I would like to order the items according to its todo.idx, instead of their (random) ordering in the data. How can I do it with polymer?
In the polymer document, it mentions a sort function, but I couldn't find examples there. My current code is as follows.
<ol>
<template is="dom-repeat" items="{{todos}}" as="todo">
<li><span> {{todo.item}} </span> </li>
</template>
</ol>
You can sort items in polymer using the sort attribute, and in your case you would want to use nested templates so you can sort on the dom-repeat for a given todo's items:
<template is="dom-repeat" items="{{todos}}" as="todo">
<template is="dom-repeat" items="{{todo.items}}" as="item" sort="_sortItems">
<li><span>{{item}}</span></li>
</template>
</template>
You can then define your _sortItems function in same fashion as you would for a compare function in Array.prototype.sort():
_sortItems: function(a, b) {
if (a.idx < b.idx) { return -1; }
if (a.idx > b.idx) { return 1; }
return 0;
}

polymer - two vaadin-grids in separate paper-tabs - populating on select

my first post and my first polymer app so I appreciate your patience. I'm using paper-tabs and iron-pages to enclose two vaadin-grids that populate via the same iron-ajax set-up - slightly different parameters. The code I have is as follows:
<ajax-api
data="{{apidata}}"
sortby="{{sortColumn}}"
gender="{{gen}}"
cat="{{category}}"
weapon="{{weap}}">
</ajax-api>
<paper-tabs selected="{{selected}}" sticky>
<paper-tab>Mens {{category}} {{weap}}</paper-tab>
<paper-tab>Womens {{category}} {{weap}}</paper-tab>
</paper-tabs>
<iron-pages selected="{{selected}}">
<div>
<vaadin-grid id="mens" items="[[apidata.mens]]" visible-rows = 15 >
<table>
<colgroup>
<col name="rank" />
.
.
.
<col name="cat" hidable="" hidden="" />
</colgroup>
</table>
</vaadin-grid>
</div>
<div>
<vaadin-grid id="womens" items="[[apidata.womens]]" visible-rows = 15>
<table>
<colgroup>
<col name="rank" />
.
.
.
<col name="cat" hidable="" hidden="" />
</colgroup>
</table>
</vaadin-grid>
</div>
Currently as you can probably see I'm using one ajax call to populate both mens and womens data at the same time - doesnt seem too efficient and is a pain when I start sorting it. The element ajax-api has two way binding that forms the parameters of an iron-ajax call and returns the data. I'd like to have the data load separately on selection of the tab. To complicate matters I'm also using the grid column renderer to re-style some of the data. I'm figuring having selection change the bound gender property will trigger my ajax element so my question is how do I do that and how can I then ensure my grid column renderer function is referencing the correct grid.
EDIT:
I thought maybe I should add the content of the Polymer function to see if that helps someone frame a response.
<script>
Polymer({
is: 'my-rankings1',
properties: {
sortColumn: {
type: String,
value: "points",
},
sortDirection: String,
sortProperty: String
},
ready: function() {
var grid = this.$.mens;
this.selected = 0;
grid.addEventListener('sort-order-changed', function() {
if (grid.size > 0) {
grid.scrollToStart();
var sortOrder = grid.sortOrder[0];
this.sortColumn = grid.columns[sortOrder.column].name;
alert(this.sortColumn);
grid.refreshItems();
}
}.bind(this));
grid.then(function() {
// Add a renderer for the index column
grid.columns[0].renderer = function(cell) {
cell.element.innerHTML = cell.row.index +1;
};
grid.columns[6].renderer = function(cell) {
if (cell.data < 0){
cell.element.innerHTML = Math.abs(cell.data) + '<iron-icon icon="arrow-downward" style="color: red"/>';
}
else if (cell.data > 0) {
cell.element.innerHTML = cell.data + '<iron-icon icon="arrow-upward" style="color: green"/>';
}
else {cell.element.innerHTML = '<iron-icon icon="settings-ethernet" style="color: #ffcc00"/>';}
};
});
},
});

Polymer 1.0 dom-repeat display index starting at 1

I am using Polymer 1.0 to create a shopping/checkout cart. I have customers who may want to ship their order to multiple addresses. In the receipt, I need to list all the addresses with an index:
Address 1
John Doe
1234 Main St
...
Address 2
Jane Smith
999 Broadway
...
How do I get the index to start at 1 instead of 0?
<template is="dom-repeat" items="{{shipping_details}}" as="address">
<div>Address <span>{{index}}</span></div>
<div>{{address.name}}</div>
<div>{{address.line1}}</div>
</template>
This is a simplification of my actual code, but the principle is the same. I have tried to make a js function that takes the index as a parameter and sets the innerHTML to index++, but I don't know what event it should fire on or how to get it to call the function.
<div>Address <span on-some-event="displayIndex(index)"></span></div>
I am new to all of this, so you can't go in to too much detail about how to make this work. Thank you for your help in advance!
You can use a computed binding for this.
Instead of this:
<span on-some-event="displayIndex(index)"></span>
Do this:
<span>{{displayIndex(index)}}</span>
When displayIndex is this:
function (index) {
return index + 1;
}
Note:
displayIndex can be
a method on the element prototype
<dom-module id="cart-addresses">
<template is="dom-repeat" items="{{shipping_details}}" as="address">
<div>Address <span>{{displayIndex(index)}}</span></div>
<div>{{address.name}}</div>
<div>{{address.line1}}</div>
</template>
<script>
Polymer({
is: 'cart-addresses',
...
displayIndex: function(index) {
return index + 1;
}
...
});
</script>
</dom-module>
a method attached to an auto-binding template
<template is="dom-bind">
...
<template is="dom-repeat" items="{{shipping_details}}" as="address">
<div>Address <span>{{displayIndex(index)}}</span></div>
<div>{{address.name}}</div>
<div>{{address.line1}}</div>
</template>
</template>
<script>
var template = document.querySelector('template[is="dom-bind"]');
...
template.displayIndex = function (index) {
return index + 1;
};
</script>

How to render template values using javascript - Meteor

how to render the contents of a template .. i can;t pass through this point :/ thanks for your help
example :
<body>
{{> dash}}
</body>
<template name="dash">
<div id="example2" class='example_block'>
<form name = "frm">
<table>
<tr>
<td>Template Name
<td>:
<td><input type="text" name = tname class = "tname">
</frm>
<div class='demo'>
<input type='button' value='Click Here to Create Window' class="btn"/>
</div>
</div>
<div id = "window_block8" style="display:none;"></div>
</template>
<template name="t1">
try1
</template>
<template name="t2">
try2
</template>
//client.js
Template.dash.events({
'click input.btn' : function(){
var temp = document.frm.tname.value ;
Session.set("template" , temp);
$('body').append(Meteor.render(Template[Session.get("currentTemplate")]()));
}
});
some thing like this.. but that code wont work on me
Meteor.render(Template.try) returns a document fragment which you can insert into your page with jQuery or vanilla JS.
e.g
Template.dash.aw = function() {
document.body.appendChild(Meteor.render(Template.try));
}
Note that you can use array-style notation if the template name is variable:
document.body.appendChild(Meteor.render(Template[Session.get("currentTemplate")]));
Alternatively, if you only want to return a variable and not an entire template:
Template.try.var = function() {
return 'Hello';
}
Template.dash.aw = function() {
return Template.try.var();
}
// Template.dash.aw = Template.try.var = function() {
// return 'Hello';
// }
The commented function is probably inadequate, since you want some logic in Template.dash.aw

Categories

Resources