This is a followup question on VUEJS remove Element From Lists?, where they give various methods (this.$remove, splice, this.$delete) for dynamically removing a element from a list. I was trying to understand how to apply this to a nested loop; here's mine in three+ levels, somewhat stripped-down:
<template v-for="(labtype,index) in labIRlist">
<template v-for="(lab,index2) in labtype">
<tr v-for="(IR,index3) in lab.irs" :key="IR.irn">
<td><p>{{ lab.hidtxt }}_{{ lab.mnem }}</p></td>
<td><p>{{ lab.PNL }}</p></td>
<td><p>{{ IR.provider}} {{ IR.psurv }}</p></td>
<td><p>{{ IR.year }}-{{ IR.eventno }}</p></td>
<td><p>{{ IR.analytes }}</p></td>
<td><p>
<button type="button"
#click="deleteIR(IR.irn,index,index2,index3)">
DELETE
</button>
</p></td>
</tr>
</template>
</template>
Then there's Javascript for the deletion
methods: {
deleteIR: function(IRNum,index,index2,index3) {
// okay, delete!
//... code to do something at the database...
alert('IR successfully deleted!')
// don't show the deleted IR any more
this.labIRlist[index][index2].irs.splice(index3,1);
},
Awful, but I didn't know how to identify the correct element. And it still didn't work (AFAIK it does nothing, no change visible to the row). How should this be done - don't we know the right element from where deleteIR was called?
What is the better way to handle deleting an element within multiple
loops?
First of all, looking at how your template is built, we can assume that your data looks something like this:
labIRlist: [
[
{
hidtxt: "TEXT 1",
irs: [{ provider: "provider1" }, { provider: "provider11" }],
irn: "irn1",
},
{
hidtxt: "TEXT 2",
irs: [
{ provider: "provider2" },
{ provider: "provider22" },
{ provider: "provider222" },
],
irn: "irn2",
},
],
[
{
hidtxt: "TEXT 3",
irs: [{ provider: "provider3" }],
irn: "irn3",
},
],
],
If you want to delete one item from the nested irs array, all you need to do is to pass the irs array and the index of the item you want to delete, no need to do the whole path you are doing currently:
this.labIRlist[index][index2].irs.splice(index3,1);
So change your template to:
<button type="button" #click="deleteIR(lab.irs, index3)">
And the delete function is then simply:
deleteIR(IRS, index) {
IRS.splice(index, 1);
}
A DEMO for your reference
PS. Please always share a bit of your data when posting questions like this. Much easier to answer when not needing to create your own sample data like I did here.
Related
Using the Ember addon ember-bootstrap I can make a set of radio buttons like this :
{{form.element controlType="radio" label="Fruit Type" property="radio" options=radioOptions optionLabelPath="label"}}
with a Controller that looks like this :
export default Controller.extend({
init() {
this._super(...arguments);
this.radioOptions = [
{
label: 'Citrus',
value: 'C',
inline: true
},
{
label: 'Non-Citrus',
value: 'N',
inline: true
}
];
}
});
The relevant doco is here https://www.ember-bootstrap.com/#/components/forms .
However what I can't do is provide a custom value to each radio button so that I end up with rendered HTML like this :
<label>Citrus</label>
<input type="radio" value="C">
<label>Non-Citrus</label>
<input type="radio" value="N">
I have looked at "Custom Controls" on https://www.ember-bootstrap.com/#/components/forms but I can't see how that applies to this case.
EDIT: Just to be clearer about why I want to do this I want to display the readable label (eg "Citrus") but have the non-readable value ("C") available to send back to the server (because the server thinks in terms of "C" or "N".
It's not essential I could send "Citrus" back and map it around on the server but I just thought this would be very straightforward.
Looking at the part of the doco starting with "You can also just customize the existing control component:" on https://www.ember-bootstrap.com/#/components/forms it does seem like you should be able to do the sort of thing I'm after but the example shown doesn't address the use of a value attribute and I can't figure out how to .
You don't need to have the HTML rendered like that. if you want to access the checked radio, simply it is the property name dot value like radio.value.
Here how to get it in the on submit action:
actions: {
onSubmit() {
alert(this.radio.value)
}
}
I had exactly the same issue but I finally solved it. You have to use form.element in block mode. Why is it also necessary to also write an action to update the value? I have no idea!
In my implementation, I'm using Ember changesets and my property is called usageType. I hope it's clear enough to adapt for your needs.
I'm also using Ember Truth Helpers, which is what the {{eq opt.value el.value}} part is. It sets checked to true if the input value is equal to the current-selected value.
# my-component.js
actions: {
selectUsageType(option) {
return this.set('changeset.usageType', option);
}
}
# usage-type-options.js (imported in component JS)
[{
label: 'First label',
value: 'A'
},
{
label: 'Second label',
value: 'B'
}]
# Etc.
# my-component.hbs
# I'm not using angle-bracket invovation here, oops
{{#form.element
property="usageType"
label="My label" as |el|
}}
{{#each usageTypeOptions as |opt|}}
<div class="form-check">
<input
type="radio"
class="form-check-input"
id="{{el.id}}-{{opt.value}}"
checked={{eq opt.value el.value}}
onchange={{action "selectUsageType" opt.value}}
>
<label for="{{el.id}}-{{opt.value}}" class="form-check-label">
{{opt.label}}
</label>
</div>
{{/each}}
{{/form.element}}
How does one work with sub-objects in handlebars? I have the following data:
{
name: "first-name-field",
spec: {
label: {
text: "First Name:"
},
input: {
type: "text",
value: ""
}
},
template: "field"
}
The field template it is referring to is as follows:
<div class="label-wrapper">
<label>
{{specs.label.text}}
</label>
</div>
<div class="input-wrapper">
<input type="{{specs.input.type}}" value="{{specs.input.value}}" />
</div>
The label section builds but the input section never appears. Im assuming this is because the scope has already changes. I have tried the ../ prefix as well, but it never sees to move back to the parent object.
In your code you have done some spell mistake. In template "specs" and in dict "spec"
Otherwise your code is working fine. I have tested your code screen short is attached.
I can't seem to find a simple way to set the title on a popup add and edit form launched from the kendoui grid, when it is created using a custom template. When I tried the following example, both Add and Edit operations had "Edit" in the title bar of the popup:
Markup:
<script id="popup-editor" type="text/x-kendo-template">
<p>
<label>Name:<input name="name" /></label>
</p>
<p>
<label>Age: <input data-role="numerictextbox" name="age" /></label>
</p>
</script>
<div id="grid"></div>
JavaScript:
$("#grid").kendoGrid({
columns: [
{ field: "name" },
{ field: "age" },
{ command: "edit" }
],
dataSource: {
data: [
{ id: 1, name: "Jane Doe", age: 30 },
{ id: 2, name: "John Doe", age: 33 }
],
schema: {
model: { id: "id" }
}
},
editable: {
mode: "popup",
template: kendo.template($("#popup-editor").html())
},
toolbar: [{ name: 'create', text: 'Add' }]
});
Fiddle demonstrating the issue: http://jsfiddle.net/codeowl/XN5rM/1/
The issue is that when you press the Add or Edit buttons, the title bar in the popup says: "Edit". I want it to say Add when you press the Add button and Edit when you press the Edit button.
Thank you for your time,
Regards,
Scott
If you want a simple solution, add code to the edit event of the grid to check to see if the model being created when edit is called is a new one or an existing one and set the text accordingly:
...
edit: function (e) {
//add a title
if (e.model.isNew()) {
$(".k-window-title").text("Add");
} else {
$(".k-window-title").text("Edit");
}
}
...
Hope this helps...
If the only thing that you need to do is add a title, you should use:
editable : {
mode : "popup",
window : {
title: "EdiciĆ³n",
}
},
You don't need to define a template unless you need to define something else.
Your modified Fiddle here : http://jsfiddle.net/OnaBai/XN5rM/2/
How do I loop thru items in a WinJS.Binding.Template within my WinJS.UI.ListView control?
My data:
{ category: 'Sports',
items: [
{ title: 'soccer'}, { title: 'tennis'}
]
}
What I want to do in my template:
<div id="myTmpl" data-win-control="WinJS.Binding.Template" style="display:none">
<h1 data-win-bind="innerText: category"></h1>
<div data-win-REPEATER="each: items">
<span data-win-bind="innerText: title"></span>
</div>
</div>
Because you want to nest the details of the items, I would recommend that you look at my answer to another question, which is very similar:
WinJS ListView and Template Binding
This has all the essential details.
That stated, theres no reason you cant integrate JQuerys templates here - you just need to find a way for them to work with the WinJS template / control contract.
Have you checked
http://code.msdn.microsoft.com/windowsapps/ListView-basic-usage-sample-fcc451db
Normally the loop is automatically (it will do based on the datasource information)
<div id="listView"
class="win-selectionstylefilled"
data-win-control="WinJS.UI.ListView"
data-win-options="{
itemDataSource: myData.dataSource,
itemTemplate: myTmpl,
selectionMode: 'none',
tapBehavior: 'none',
swipeBehavior: 'none',
layout: { type: WinJS.UI.GridLayout }
}"
></div>
I've got basically two arrays of objects in one view:
App.List = Ember.View.extend({
students: [{ "name": "yehuda" }, { "name": "tom" }],
teacher: [{ "name": "mr. katz" }, { "name": "mr. dale" }]
});
My handlebars look something like this:
{{#each teacher}}
<li class="teacher">{{name}}</li>
{{#each students}}
// display students for this teacher
{{/each}}
}}
The obvious problem here is, that the students-array is not within the teacher-array but on the same "level". So how can I access the students-array?
Thanks!
It seems to be related to the view context, try to use {{view.students}}, I think it should work.
jsfiddle updated against comments: http://jsfiddle.net/Sly7/gdXfN/