Closed dpinart closed 8 years ago
You can make it work by creating elements dynamically polymer way:
// Create tabs element
let tabs = document.createElement('paper-tabs');
Polymer.dom(yourContainerElement).appendChild(menu);
// Generate tabs
for (let i = 0; i < tabs.length; i++) {
let tab = document.createElement('paper-tab');
Polymer.dom(tab).textContent = 'Tab title ' + i;
Polymer.dom(tabs).appendChild(tab);
}
hmm, thanks, it's interesting.
Does anybody know how to attach custom attributes progamatically to HTML Elements?
I've found a more "aurèlia" friendly approach, not ideal though. I have created a viewModel with no view that dynamically builds the template and returns an InlineViewStrategy. Somethinglike(typescript):
export class TabPanelViewModel{
public actions: ActionItem[];
public activate(actions: ActionItem[]){
this.actions = actions;
}
public getViewStrategy(){
let template = '<template><paper-tabs selected="0">';
for(let i = 0; i < this.actions.length; i++){
template += '<paper-tab><compose view-model.bind="actions[' + i + '].viewModel" model.bind="actions[' + i +'].model"></compose></paper-tab>';
}
template += '</paper-tabs></template>';
return new InlineViewStrategy(template);
}
}
This way, the markup contains a paper-tabs with all paper-tab items, so when is added to the DOM polymer paper-tabs knows about its children.
Then, at view:
<compose class="bottom self-end fit" view-model="'./tab-panel}" model.bind="items"></compose>
I'm using the same pattern for paper-toolbar and it works fine too
my experience is that Polymer requires sometimes that you use its DOM manipulation (append, remove) functions to make components work correctly.
so the InlineViewStrategy may look more Aurelia way, but if you will try for example dynamically change the tabs it will again not work if you don't use Polymer/append methods.
Well, I implemented an small hack to force the ViewModel to reload, basically, the view-model in compose element has bind with a condition like
<compose class="bottom self-end fit" view-model="{items.length ? './tab-panel' : './empty'}" model.bind="items"></compose>
'empty' is just an empty template, so if I want to rebind tabs I have to clear items array and then repopulate it with the new items.
It's not the more elegant solution and obviously I'd prefer the repeat.for option working properly, but I think right now I prefer InlineViewStrategy over Polymer DOM manipulation because it allows more flexibility and the syntax is the same I use for other templates. (And thanks to JSX support in many IDEs typing the template in .js files it's quite easy and no so error proune
Obviously, I can find scenarios where InlineViewStrategy does no fit well and I have to use Polymer programatically.
Anyway It's nice we can offer several workarounds for this issue...
I think it's the same thing as #12, where Aurelia adds a template element that the Polymer elements are written to ignore. The <template>
shows up using Polymer.dom
but not in Chrome's inspector, I'm guessing since Polymer.dom
shows the shadow DOM web component elements and Chrome expands them out with the generated HTML. The IronSelectable
behavior uses Polymer.dom.queryDistributedElements
, which doesn't seem to peek into the <template>
, to find items, so it only sees that template element, which it ignores.
PolymerElements/iron-selector#42 might fix it.
The following example seems working for me. So, I'm not sure what the matter is. Bellow might not make sense.
<paper-tabs>
<paper-tab repeat.for="item of items">${item}</paper-tab>
</paper-tabs>
This one does not because paper-tabs does not recognize sub children of the child element, I made au-select attribute that gathers all children and sub children under In the following example, paper-tabs works au-select with The above code was borrowed from PolymerElements/iron-selector#42. Or, the following code can be added to main.ts to replace the default behavior, if you don't want to use the au-select attribute. Closing this since <paper-tabs>
<div>
<paper-tab repeat.for="item of items">${item}</paper-tab>
</div>
</paper-tabs>
<paper-tabs au-select selectable=".selectable_item">
<div>
<paper-tab class="selectable_item" repeat.for="item of items">${item}</paper-tab>
</div>
</paper-tabs>
// resources/au-select-custom-attribute.ts
// add aurelia.use.plugin('resources/au-select-custom-attribute') to main.ts
import { autoinject } from 'aurelia-framework';
@autoinject
export class AuSelectCustomAttribute {
constructor(private element: Element) {
(<any>element)._updateItems = function() {
//var nodes = (<any>window).Polymer.dom(this).queryDistributedElements(this.selectable || '*');
var nodes = (<any>window).Polymer.dom(this).querySelectorAll(this.selectable || '*');
nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
this._setItems(nodes);
}
}
}
export function configure(aurelia: Aurelia) {
(<any>window).Polymer.IronSelectableBehavior._updateItems = function() {
//var nodes = win.Polymer.dom(this).queryDistributedElements(this.selectable || '*');
var nodes = (<any>window).Polymer.dom(this).querySelectorAll(this.selectable || '*');
nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
this._setItems(nodes);
}
au-select
seems to work, but reopen if it's still an issue
Hi I have a view with a paper-tabs element. The paper-tabs contains a repeat.for that creates a set of paper-tab items similar to:
Despite at first look it seems above snippet works fine it doesn't. Parent paper-tabs items property is empty, so interacting with any paper-tab children does not has any effect on the paper-tabs as it doesn't belongs to the paper-tabs.
I suspect a similar issue exists with paper-toolbar.
Is there any way to dynamically populate a paper-tabs element?
Thanks