Iterate form fields in Vue.js - vue.js

I have a list of products and my product items have some specifications that are different depending on what type of product has been selected. So instead of making 3 different edit forms (1 for each product) I want to iterate over each form field in the list of my specifications.
However I can't use v-model on an iteration so I have to bind it to the :value, however I can't bind these values back dynamically to my form object.
How can I make my form dynamic by iterating over an object and binding it back to my form payload?
v-for
<div v-for="(spec, index) in item.specs" :key="index">
{{spec}}
<v-text-field :name="spec" :label="index" :value="spec"></v-text-field>
</div>
Object
I fill this object from my API return this.specs = response.data.specs
specs:{}

you can use v-model for two-way data bindings. As
<div v-for="(spec, index) in item.specs" :key="index">
{{spec}}
<v-text-field :name="spec" :label="index" :value="spec" v-model='item.specs[index]'></v-text-field>
</div>

Related

Is it possible to not omit some opts on the outermost element in a custom Riot tag?

I'm using RiotJS v3.9
I've written a custom tag that accepts a few opts. The problem is that the markup it generates includes all of those opts on the outermost element, in addition to the interior tags where I explicitly deposit them. I do not want any opts to appear on the top element unless I make that happen.
In this case, my custom tag display a list of items. One of the opts it accepts is the value for a specific data- attribute on each list item. So, I want data-something={opts.itemSomething} to appear on each list item, but I do not want that to appear on the wrapper.
// my-list.tag
<my-list>
<ul data-something={ opts.something }>
<li
each={ item in opts.items }
data-something={ parent.opts.itemSomething }
>
{ item }
</li>
</ul>
</my-list>
Using it:
<my-app>
<my-list
something="parent-value"
item-something="child-value"
items={['one', 'two', 'three']}
/>
</my-app>
What it emits into the page:
<my-list something="parent-value" item-something="child-value">
<ul data-something="parent-value">
<li data-something="child-value"> one </li>
<li data-something="child-value"> two </li>
<li data-something="child-value"> three </li>
</ul>
</my-list>
I don't want the emitted <my-list> tag to have either the parent-value or the child-value on it. I only want those attributes to appear on the <ul> and <li>, like I coded it.
// bad output
<my-list something="parent-value" item-something="child-value">
// good output
<my-list>
Is this possible?
Also, I know from working with React that I'm likely to encounter future cases where I want some of the opts to appear on the wrapper while hiding others. So, ideally I'd like to know how to control this behavior on a per-opt basis.
you can remove the unwanted attributes in both the "updated" and "mount" event.
check this demo
However I strongly suggest you to switch to riot#5!!

how to interpolate a value into an HTML attribute without binding to anything on the Vue instance

The title was kinda long-winded but the question itself is pretty simple.
So I'm looping over some strings and want to make a button for each. On click, the button will call a Vue method. I want to bind the string into the HTML element somehow - it will be more clear with the code:
<li v-for="(name, idx) in $store.state.lobby" :key="idx">
<button data-name="{{name}}" v-on:click='send_game_request'> request game </button>
</li>
so, as you can see, this is very simple. When the send_game_request method gets run, it can read the name off the data-name attribute and do what it needs to with that information.
But, this is invalid syntax, because {{name}} raises an error. I'm really hoping I don't have to wrap each button into it's own sub-component, because that is just extra boilerplate that's not necessary.
I've seen other examples that use v-bind but I don't really have any need to store this information in the component's internal state. I literally just need to know what button was pressed.
You can pass the name as an argument with an inline handler:
<button #click="send_game_request($event, name)">
where $event is the original event data.
In addition to what Tony mentions in his answer,
<li v-for="(name, idx) in $store.state.lobby" :key="idx">
<button :data-name="name" v-on:click='send_game_request'> request game </button>
</li>
You could then extract value of name with datasets like so:
function send_game_request(event){
const name = event.target.dataset.name;
}
NOTE: In this instance you don't need to explicitly pass the $event into your v-on:click function binding, it will already be made available by Vue. So, you can simply invoke your method with the event argument.

v-select displays object Object

I'm new to vuetify and I'm stuck on how to properly use v-select. I'm pulling the select values from an API to a store called FormatTypes that looks like this:
[{"id":5,"formatlabel":"RDBMS Table or View"}
,{"id":6,"formatlabel":"Microsoft Access"}
....
,{"id":23,"formatlabel":"ArcGIS for Server image services"}]
my v-select:
<v-select font-weight-regular subtitle-1
v-model=dataset.formattypeid
:name="FormatTypes"
:items="FormatTypes"
:item-value="FormatTypes.id"
:item-text="FormatTypes.formatlabel"
:label="FormatTypeLbl"
:outlined=true
>
I've used the item-text/item-value props but I'm still getting the "object Object" in the display.
You don't have to use binding and no need to link it back with the items in item-value and item-text
<v-select font-weight-regular subtitle-1
v-model=dataset.formattypeid
:name="FormatTypes"
:items="FormatTypes"
item-value="id" // No need of binding and no need of FormatTypes linking
item-text="formatlabel" // No need of binding and no need of FormatTypes linking
:label="FormatTypeLbl"
:outlined=true
>

vue.js - Change text based on default/clicked class

Given the following:
<div id="#my-container">
<div class="title">Companies</div>
<div class="tab active tab-apple">Apple</div>
<div class="tab tab-google">Google</div>
</div>
When page is loaded without any tab clicks yet, whichever tab with the default active class, needs to go in the .title div. For the example above, <div class="title">Apple</div>
On click of a tab, the class is switched to active, and vue.js needs to update the .title div once again.
How can this be done with vue.js? I've tried but not able to get it to work as intended.
The answer by David is one way to do it. But Vuejs offers in-line computations for this. So, no need to hook into any CSS event. Here's some code to explain:
Create a data property active_tab, just like David mentioned. And then bind it's value just like he's done it. In your tabs, add an click event and at that event, assign appropriate value to active_tab.
<div class="tab active tab-apple" #click="active_tab = Apple">Apple</div>
<div class="tab tab-google" #click="active_tab = Google">Google</div>
Now, to dynamically assign the active class to the respective tab, make the class attribute, a computed property, like this:
<div
:class="['tab', active_tab == 'Apple' ? 'active' : '', 'tab-apple']"
>
Apple
</div>
What this code is basically doing is, :class makes class a computed property. Then the commas in the array divide the statement. So, the computation will always add tab and tab-apple classes. But, only if active_tab == 'Apple' then ? add 'active' else : add ''
Not sure which CSS framework you are using, but normally I hook into the events thrown by the tab switching (many CSS frameworks provide this access). Once hooked into it, you can write a Vue custom directive that will take that event and use it to update a VM attribute that indicates which tab is active.
Then you can use normal mustache templating to get it into your template:
<div class="title">{{ active_tab }}</div>

How do i set the id in WinJS.Binding.Template in a Win8 App

The following html is not working for me.
<div id="weightListViewTemplate" data-win-control="WinJS.Binding.Template">
<span data-win-bind="innerText: name; id: id"></span>
</div>
<div id="basicListView" style="width:420px;height:600px" data-win-options="{ itemTemplate: select('#weightListViewTemplate') }"
data-win-control="WinJS.UI.ListView">
</div>
The list appears but the ID property is not set on the span objects.
How to a set the id of the span dynamically in the template based on the corresponding value in the datasource/array?
I wouldn't recommend using the actual ID property. I believe you can't set it through data binding -- I believe WinJS uses ID's on elements under the covers to allow for weak-references to the DOM elements. Because of this it doesn't let you set the ID.
I would suggest using another property or attribute instead.