Polymer dom-if doesn't restamp computed condition under dom-repeat - javascript

So I have a scenario:
<template is="dom-repeat" items="{{objects}}" as="o" filter="{{_filter(filter)}}">
...
<template is="dom-if" if="_isHidden" restamp>
foo
</template>
...
</template>
Now, the _filter function forces rerendering items under the dom-repeat every time my filter property changes (since it's observed by _filter. This is not the problem as it works properly, but the catch is that the _hidden function might return true or false based on another property (which could also change), and whenever the filter rerenders I need to force re-evaluation of _isHidden hence hide or show the contents of the dom-if template.
Anyone has an idea what could be my issue?
Thanks!

You have to also bind the _isHidden property:
<template is="dom-repeat" items="{{objects}}" as="o" filter="{{_filter(filter)}}">
...
<template is="dom-if" if="{{_isHidden}}" restamp>
foo
</template>
...
</template>

Related

Vue Named Slots Caveat?

When using Named Slots with Vue (utilizing the older, more verbose API for component slots), if I have a reusable component defined with a template like this:
<template>
<div v-for="field in formFields">
<slot name="`${field.key}_PREPEND`">
<span hidden></span>
</slot>
<slot name="`${field.key}_FIELD`">
<slot name="`${field.key}_LABEL`">{{ field.label }}</slot>
<slot name="`${field.key}_CONTROL`">
<input v-if="field.type === 'text'" v-model="model[field.key]"></input>
<input type="checkbox" v-else-if="field.type === 'checkbox'" v-model="model[field.key]"></input>
</slot>
</slot>
<slot name="`${field.key}_APPEND`">
<span hidden></span>
</slot>
</div>
</template>
(this is essentially a hollowed out version of an auto-form generating component I have)
I can then reuse this component like so:
<auto-form
:fields="someArray"
:model="someObject"
>
<template slot="Name_PREPEND"> This goes before the name field </template>
<template slot="Name_FIELD"> For some reason this isn't being rendered, the default slot markup is</template>
<template slot="Name_APPEND"> This goes after the name field </template>
</auto-form>
For some reason, using the above markup (<auto-form>), the slot "${field.key}_FIELD" is ignored.
If I change the inner markup of the _PREPEND field like so
<slot name="`${field.key}_PREPEND`">
<span hidden>
<slot name="`${field.key}_CONTENT`"></slot>
</span>
</slot>
I similarly cannot override the _PREPEND slot (but can override _CONTENT)
Is this simply a limitation of Vue component slots? i.e. Are nested component slots not allowed?
In this particular case, the limitation would prevent a developer using this AutoForm component from say, overriding both the control and label at once via the _FIELD slot (for my uses I wanted to add logic that made a particular field conditional based on the value of other fields in the form)
In case anyone else runs into this issue, it's a bit of a sneaky one.
It looks like if you do conditional rendering on markup that is supposed to override a slot, the default slot will render in its place when it is not conditionally rendered.
So, the simple solution is to use v-show instead of v-if when you try to override the component slot.
(Has nothing to do with nested component slots as originally suspected)

Using v-edit-dialog with components?

i had a question about the v-edit-dialog component that vuetify offers. So, the way i am rendering my v-data-table is such that i am importing a component with props into a template slot. According to the documentation link, it seems like the data table has to be rendered directly, like this codepen.
So i am not sure how i can make the v-edit-dialog work using my approach.
Here is what my code looks like:-
<template>
<v-data-table>
<template v-slot:items="props">
<my-component
:protein="props.item.protein"
:carbs="props.item.carbs"
:fats = "props.item.fats"
:iron="props.item.iron"/>
</template>
<v-data-table>
</template>
I am sorry guys, i don't know how i can duplicate this issue but i hope you get some idea. Again, thank you in advance.
You should take a look at the documentation for component props.
What you have done by now is correct and should work, only if you have setup your component my-component correctly:
<!-- my-component example -->
<template>
<v-edit-dialog :return-value.sync="protein">
{{ protein }}
<template v-slot:input>
<v-text-field
v-model="protein"
:rules="[max25chars]"
label="Edit"
single-line
counter
/>
</template>
</v-edit-dialog>
</template>
<script>
export default {
name: 'my-component',
props: {
protein: {
type: String,
default: '',
}, //... the rest of the props you want to access
},
}
</script>
In order to make the protein and other props edit/mutate/update your props.item.protein etc, you have to add a sync modifier to the prop.
<template>
<v-data-table>
<template v-slot:items="props">
<my-component
:protein.sync="props.item.protein"
:carbs.sync="props.item.carbs"
:fats.sync="props.item.fats"
:iron.sync="props.item.iron"/>
</template>
<v-data-table>
</template>
Else, you will get a vue error "you should not mutate an prop directly"
<template v-slot:items="props">.
for this eazy right is
<template v-slot:items="{ item }">
<my-component
{{item. protein}}

Polymer Iron-selector - Deselect the template on Save

I am having odd behavior with Polymer 1 Iron-selector
Below is my code.
<iron-selector selected="{{_selectedIndex}}">
<template is="dom-if" if="[[colors.length]]">
<colors-item colors="[[colors]]"></colors-item>
</template>
<template is="dom-repeat" items="{{colorways}}">
<colorway-item colorway="{{item}}"></colorway-item>
</template>
and in Properties selectedIndex looks like this
_selectedIndex: Number,
If I make changes and save, I want the selected to be none. How can i do this?

Polymer modeling template within template

I'm trying to create dropdown select (appearing if radio button is selected) in Polymer, that triggers another dropdown select on-iron-select.
All of this lives within a parent template:
<dom-module id="likes-cars">
<template id="maintemplate">
<paper-radio-button checked="{{likesCars}}" id="thebutton">I like cars.</paper-radio-button>
<template is="dom-if" if="{{likesCars}}">
<paper-dropdown-menu label="Your favourite car make">
<paper-menu class="dropdown-content" on-iron-select="modelfunc">
<paper-item>Make 1</paper-item>
<paper-item>Make 2</paper-item>
</paper-menu>
</paper-dropdown-menu>
</template>
<template id="menutemp">
<paper-dropdown-menu label="Your favourite car model">
<paper-menu class="dropdown-content" >
<template is="dom-repeat" items="{{models}}"id="modelstemplate" >
<paper-item>{{item}}</paper-item>
</template>
</paper-menu>
</paper-dropdown-menu>
</template>
</template>
And my Polymer script once the iron-select occurs is:
<script>
Polymer({
is:"likes-cars",
modelfunc: function() {
this.$.menutemp.model={}
this.$.modelstemplate.model={models:["Model 1","Model 2"]}
}
});
</script>
This results in the error:
Uncaught TypeError: Cannot set property 'model' of undefined
What is the best way to select and model "modelstemplate" with an array passed in?
Do I need to model the template around it("menutemp") separately?
I think you're misunderstanding how Polymer's data binding works a bit.
When you bind to something using the [[property]] or the {{property}} notation in a custom element, you're binding to the custom element's properties, no matter if you actually define the properties when calling the Polymer() function.
So when you say your dom-if and your paper-radio-button are bound to likesCars and that the dom-repeat is bound to models they're bound to this.likesCars and this.models.
So all you need to do in your modelfunc function is to set this.models to an array of Strings you want to show as items for the second menu. With this considered, the template enveloping the second menu is actually unnecessary.
Here's a jsbin with a working example based on your code, I added a selectedMake property too so that you can actually set different arrays to the second menu depending on what was selected on the first menu.
I hope this helped

How to update the dom-repeat template to display newly added item in localstorage?

<template id="repeat" is="dom-repeat" items="[[model]]" as="day">
<component model="[[day]]"></component>
</template>
I am using iron local storage to load data as the [[model]].
When the data is updated using localStorage.setItem(...), how can I have the template to update and display the newly added object?
Right now the new object only displays after a page refresh, because it will reload the local storage.
I tried using this.$.repeat.render() as said by another stackoverflow post but that did nothing.
That pattern I would use would be:
<template>
<iron-localstorage name="my-app-storage" value="{{model}}" on-iron-localstorage-load-empty="initializeDefaultValue"></iron-localstorage>
<template id="repeat" is="dom-repeat" items="[[model]]" as="day">
<component model="[[day]]"></component>
</template>
</template>
And then when you want to update localstorage, just update the object because:
iron-localstorage automatically saves the value to localStorage when value is changed. Note that if value is an object auto-save will be triggered only when value is a different instance.
this.set('model', model);

Categories

Resources