I have used a method in the past to make paper-inputs blank in the past, however my usual methods are not working when in conjunction with Vaadin-grid.
Am I missing something here?
Vaadin-grid HTML
<vaadin-grid-column>
<template class="header">
<div class="horizontal layout cell">
<label for="keyFilter" class="keyText cell flex">Key</label>
<vaadin-grid-filter class="cell" id="keyFilter" path="key" value="[[_filterKey]]">
<paper-input no-float-label class="keyFilter" id="keyFilter" slot="filter" placeholder="Filter search" value="{{_filterKey::input}}" focus-target on-input="clearAppear" >
<iron-icon suffix icon="clear" class="clearIcon" on-click="clearField" clear-item-id="keyFilter"></iron-icon>
</paper-input>
</vaadin-grid-filter>
</div>
</template>
<template class="cell">[[item.key]]</template>
</vaadin-grid-column>
I have attempted the following JS:
// Attempt 1 - gives "undefined" within the dev tools
this.$.keyFilter.value = '';
// Attempt 2 - finds the correct element, but does not set the value to blank
document.getElementById('keyFilter').value = ''
For locating dynamically-created nodes in your element's shadow DOM, use the standard DOM querySelector method:
this.shadowRoot.querySelector(selector)
So, for your problem use this.shadowRoot.querySelector("#keyFilter").value='';
And you have done a simple mistake in the above code i.e. providing same id name for vaadin-grid-filter and paper-input element. Make sure to change this before trying the above code.
Related
I am dynamically generating $ref names using a template for-loop.
If I console log a specific item in the for-loop (see example), it can be reached. However when I take that same reference and call a function on it like focus() or scrollToView(), the console becomes woefully confused and throws an error:
vue.js:1743 TypeError: this.$refs.element2.focus is not a function
So just to be clear:
console.log(this.$refs['element2']); <-- WORKS!
this.$refs['element2'].focus(); <-- DOESNT WORK :(
https://jsfiddle.net/3xj7afgh/238/
Here's your template from the fiddle:
<div v-for="(result, index) in data" :key="index">
<input type="text" type="file" :ref="'element' + result.id" />
</div>
The following excerpt from the docs applies in this situation:
When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances.
So you'd need to do this:
this.$refs['element2'][0].focus()
Mixing dynamic refs and v-for can get messy, as you can see.
Alternatively you can use a static ref to achieve the same sort of thing:
<div v-for="(result, index) in data" :key="index">
<input type="text" type="file" ref="elements" />
</div>
// Index 1 is the second element in the DOM
this.$refs.elements[1].focus()
I am using polymer 1.
I have used something like this in polymer and I am passing the section's content from the point where i use this component.
It's working fine for chrome and firefox.
But for IE-11, I am not getting anything for the content.
<section id="asdf" class="className">
<content select="section"></content>
</section>
Does someone know the about this issue ?
Try setting the select attribute value to contain a period. The select attribute needs a selector not a string.
<template>
<header>Local dom header followed by distributed dom.</header>
<content select=".content"></content>
<footer>Footer after distributed dom.</footer>
</template>
Polymer docs
I'm writing reusable components for our internal framework that abstract away some monkey code. Most of the scenario's are implemented with slots and work great. However, some scenario's require rendering templates inside for loops, and unfortunately slots aren't supported there.
I came up with the following (working) code:
<template>
<div class="form-group">
<label for.bind="titleSafe" class="control-label">{title}</label>
<select id.bind="titleSafe" value.bind="value" class="form-control">
<option repeat.for="item of itemsSource" >
<template replaceable part="item-template" containerless>${item}</template>
</option>
</select>
</div>
</template>
This code has, IMO, multiple issues that make it a bad candidate for including it in a framework:
It doesn't support default templates like slots does, so when you have only 1 replacable part the syntax is needlessly verbose
Having to use 2 different templating systems (slots + replace-part) in my project seems really counter intuitive and will certainly create confusion/bugs in my dev team
When you use template parts in the example I provided above, you need to know I declared 'item' as iterator in my for loop in order to construct your template correctly
Therefore I went looking for alternatives. After some research I came up with something like this:
<template>
<div class="form-group">
<label for.bind="titleSafe" class="control-label">{title}</label>
<select id.bind="titleSafe" value.bind="value" class="form-control">
<option repeat.for="item of itemsSource" >
<!-- I want to insert my custom element here -->
</option>
</select>
</div>
<slot></slot>
</template>
The above is my select-item custom element. Then I would also create another custom element for the templating of the repeatable item, like select-item-template, I would then use the two together like this:
<select-item title="myTitle" items-source="myItems">
<select-item-template><span>${myItemsProperty}</span></select-item-template>
</select-item>
The strength of this approach would be that you can create complex 'root' custom elements with one default slot. In this slot, you could then define multiple custom 'child' elements that the root element can search for when it's initialized (I know you can do this with the #child and #children decorators, so that part is covered). I'm a bit lost on how I would have to use these custom child element's content in my root custom element though.. How would I take my span element in the above example and prepare it's content to be rendered in the repeater? And would it be possible to take the repeated item set it as the template's datasource so I don't have to specify itemin my templates?
I hope I didn't make this too verbose, but I wanted to explain what my functional requirement is. If you have any resource that can point me in the right direction I would be very grateful!
Use the processContent attribute to transform the element content into a part replacement. The component will still use replace-part internally but consumers of the component won't be exposed to this implementation detail.
https://gist.run?id=2686e551dc3b93c494fa9cc8a2aace09
picker.html
<template>
<label repeat.for="item of itemsSource" style="display: block">
<input type="radio" value.bind="item" checked.bind="value">
<template replaceable part="item-template">${item}</template>
</label>
</template>
picker.js
import {bindable, processContent} from 'aurelia-templating';
import {bindingMode} from 'aurelia-binding';
import {FEATURE} from 'aurelia-pal';
#processContent(makePartReplacementFromContent)
export class Picker {
#bindable itemsSource = null;
#bindable({ defaultBindingMode: bindingMode.twoWay }) value = null;
}
function makePartReplacementFromContent(viewCompiler, viewResources, element, behaviorInstruction) {
const content = element.firstElementChild;
if (content) {
// create the <template>
const template = document.createElement('template');
// support browsers that do not have a real <template> element implementation (IE)
FEATURE.ensureHTMLTemplateElement(template);
// indicate the part this <template> replaces.
template.setAttribute('replace-part', 'item-template');
// replace the element's content with the <template>
element.insertBefore(template, content);
element.removeChild(content);
template.content.appendChild(content);
return true;
}
}
usage
<template>
<require from="picker"></require>
<h1>Default Item Template</h1>
<picker items-source.bind="colors" value.bind="color"></picker>
<h1>Custom Item Template</h1>
<picker items-source.bind="colors" value.bind="color">
<em css="color: ${item}">
${item}
</em>
</picker>
</template>
I have this dom-repeat template in polymer
<template is="dom-if" if="true">
<typeahead items="{{item.children}}"></typeahead>
</template>
<template is="dom-repeat" id="level" items="{{item.children}}">
<li on-click="itemClickHandler" id$="[[getItemId(item)]]" class$="{{isItemSelected(item, selectedItem)}}" >
<template is="dom-if" if="[[!toShowColumnTypeahead()]]"><span>{{getItemLabel(item)}}</span></template>
<template is="dom-if" if="[[toShowColumnTypeahead()]]">
<template is="dom-if" if="[[!item.searchTerm]]" restamp="true">
<span class="f">{{getItemLabel(item)}}</span>
</template>
<template is="dom-if" if="{{item.searchTerm}}" restamp="true">
<span class="">{{item.currentSearchLabel.prefix}}<span class="bold">{{item.currentSearchLabel.highlight}}</span>{{item.currentSearchLabel.suffix}}</span>
</template>
</template>
<button class$="[[getItemOpenerClass(item)]]" on-click="openClickHandler" key$="[[getItemId(item)]]">Open</button>
<template is="dom-if" if="{{_hasChildren(item, showChevron)}}">
<span class="chevron"><i class="fa fa-angle-right"></i></span>
</template>
</li>
</template>
The data for item.children is changing from typeahead polymer component and its notifying it. however if the items.children is modified and was still part of previous result then it is not redrawn on dom, I want it to be redrawn on DOM every time there is any change in the list irrespective of whether it was part of previous change or not. Right now Polymer only redraws the changed elements on the DOM. I tried so many thing from net from this.set to manually calling the render method by query selecting the template.
I'm not entirely sure I follow you 100% but you could try using restamp on the dom-repeat, forcing it to destroy and recreate elements every time item.children is changed.
Ignore this, restamp actually only works on dom-if
Render will synchronously force rendering the changes that will usually be done asynchronously, but it only picks up changes made through the Polymer API, so you might want to make sure the changes made to your item.children are made through the Polymer API and not just native array function (i.e the thing setting it should do something along the line of this.push('theArray', newItem) instead of the usual theArray.push(newItem)).
Edit: to further clarify:
calling render "just" forces to re render the changes synchronously, but this shouldn't force rendering more stuff than the usual asynchronous rendering
your issue probably comes from how the array is updated. Use this.splice, this.push, this.pop, this.unshift or this.shift to mutate your array. Link to the doc
I display a list of bars in a NgRepeat and I use the value frecuency to display the width of bars in percentage. From what i see IE 9-10 doesn't like this part: style="width:{{type.frecuency}}%;"
<div class="drp" ng-repeat="type in weeks">
<div style="width:{{type.frecuency}}%;" class="percentBar">
<span ng-if="type.frecuency > 14">{{type.frecuency}}%</span>
</div>
</div>
Is this an issue with Angular on IE or my code is the problem.
Thanks
P.S.
I know that i could make a class but modifying the style attribute is faster.
Solution: ng-style="setBarWidth(type.frecuency);"
scope.setBarWidth = function(width) {
return {width: width+'%'};
};
When using derived values for various HTML attributes, it's always a good idea to use the provided Angular directives to do it. They make sure that the browser sees the values you want it to see and not the binding syntax (in your case {{type.frecuency}})
Here, the ngStyle directive should be used.
<div class="drp" ng-repeat="type in weeks">
<div ng-style="width:{{type.frecuency}}%;" class="percentBar">
<span ng-if="type.frecuency > 14">{{type.frecuency}}%</span>
</div>
</div>
There are similar directives for many other HTML attributes, see the documentation for the full list.