I have a table in which I have particular column as checkboxes. I have assigned a empty list. So what I want is that I want the ids of the rows of the enabled checkboxes. Say for example if the checkboxes are enabled in id 4 and 5 then the list should be [4,5]
Sample data:
{ id:1,
name: "A",
qty: 6,
value: 10
},
{ id:2,
name: "B",
qty: 4,
value: 10
},
{ id:3,
name: "C",
qty: 1,
value: 10
}
Getting data from service:
ngOnInit(): void {
this.dataService.getData().subscribe(res => {
this.listes = res;
});
}
List name:
checkboxselectlist: any[];
My stackblitz: https://stackblitz.com/edit/angular-ivy-4vnwed?file=src%2Fapp%2Fapp.component.ts
This should help you.
You need to pass an event handler to ngchange.
In the event handler, you can get the element id which should help you to update your list. checkboxselectlist
// in your app.component.ts
filterResults(obj: any, e: any) {
console.log(obj);
console.log(e.currentTarget.checked); // true or false
// UPDATE LIST HERE
}
// in your app.component.html
<tr *ngFor="let list of listes; index as i">
<td>{{i+1}}</td>
<td>{{list.name}}</td>
<td>{{list.qty}}</td>
<td>{{list.value}}</td>
<td> <input type="checkbox" id="vehicle1"
name="vehicle1"
(change)="filterResults(list, $event)">
</td>
</tr>
Related
<script>
import { datalist } from "./datalist";
export default {
name: "HelloWorld",
components: {},
data() {
return {
items: datalist,
};
},
methods: {
deleteEvent(id) {
this.items = this.items.filter((e) => e.id !== id);
},
},
};
</script>
My data...
export const datalist = [
{ id: 1, val: "11", kk: "potter" },
{ id: 2, val: "22", kk: "james" },
{ id: 3, val: "55", kk: "limda" },
{ id: 4, val: "77", kk: "stepen" }
];
<div>
<div v-for="item in items" :key="item.id">
<b>{{ item.id }}.</b>
<router-link :to="{ name: 'UserWithID', params: { id: item.id } }">
{{ item.kk }}
</router-link>
<input type="checkbox" :value="item.id" />
<button #click="deleteEvent(item.id)">Delete</button>
</div>
</div>
My complete code;- https://codesandbox.io/s/wild-flower-rssg0?file=/src/components/datalist.js
I want to delete the array item, When user click on checkbox beside each item. and then click on delete button then the array item record need to be deleted.
But now i am getting as, Directly if I click on delete button, i am able to delete the array. But that should happen only after the checkbox click and then delete button.
For this process, I have taken click event in button and added a method to delete array record but its not working.... Can u please help me what is wrong with the code...
You should maintain an array of items to delete. Bind the checkbox to this array so that if the checkbox is checked, the item ID is added to this array. Then, simply add a delete button somewhere to delete all selected items.
See example here: https://codesandbox.io/s/elated-lake-ws2wn
I'm working with BootstrapVue.
I have following problem. I have a b-form-input where I'm searching for my number over my b-form-select. So I'm selecting 3 values and get a number in my input field and other way around - so it's an Autofill.
This works fine - and because of that I think I don't need to show you the code.
The problem is that I want to disable all selects (instead of the first) till the field before was selected.
I have problem that if I have multiple elements all will be updated. So if I input something in Input1 in the first element the second Input of all other elements will be !disabled
Additional Info: IDParent is a prop!
If you need any additional code, I can update my question!
<template>
<div>
<div class="mt-2" v-for="(IDChild, indexChild) in inputs" :key="indexChild">
<div>
<div class="mt-2">Number</div>
<b-form-input type="number" v-model="IDChild.Number" :value="IDChild.Number"></b-form-input>
</div>
<div>
<div class="mt-2">Input 1</div>
<b-form-select v-model="IDChild.Input1" :value="IDChild.Input1" :options="optionsInput1" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 2</div>
<b-form-select :disabled="disabledInput2" v-model="IDChild.Input2" :value="IDChild.Input2" :options="optionsInput2" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 3</div>
<b-form-select :disabled="disabledInput3" v-model="IDChild.Input3" :value="IDChild.Input3" :options="optionsInput3" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
</div>
<!-- add new element when button was clicked -->
<div class="mt-4 mb-5 ml-3 mr-3">
<b-button #click="addElement"> Add Element </b-button>
</div>
</div>
</template>
my script:
<script>
import json from "./json/json.json";
export default {
name: "Test",
methods: {
addElement() {
this.inputs.push({});
},
searchNumber(input, IDParent, indexChild) {
input.Number = "";
this.json.forEach((element) => {
if (
element.Input1 == input.Input1 &&
element.Input2 == input.Input2 &&
element.Input3 == input.Input3
) {
for (const key of Object.keys(element)) {
input[key] = element[key];
}
}
});
if(input.Input1) {
this.disabledInput2 = false;
}
if(input.Input2) {
this.disabledInput3 = false;
}
},
},
props: [
"IDParent",
],
data() {
return {
inputs: [{}],
json: json,
disabledInput2: true,
disabledInput3: true,
};
},
};
</script>
What you are missing is a multi-layer model for your data which you can call in your searchNumber function and call for your :disabled attribute.
In your v-for="(IDChild, indexChild) in inputs" you could use IDChild or indexChild for that. For example you would call :disabled="disabledInput2[indexChild]". That way you would refer to disabledInput2 with the specific indexChild.
You also need to handle this in your function, for example this.disabledInput2[indexChild] = false;.
Basically it´s the same as storing multi-layer data in the same object with v-model.
EDIT: Generally Example
I´ve created the following properties for this example. We have myNumberInput as an object to handle multiple input fields for numbers. mySelectionData provides a simple collection of two objects with 3 selection arrays each. myDisableData is the object that will handle multiple disabled attributes for this selections:
myNumberInput: {},
mySelectionData: {
1: {
1: [
{ name: "1A", value: 1 }, { name: "2A", value: 2 }, { name: "3A", value: 3 }
],
2: [
{ name: "4A", value: 4 }, { name: "5A", value: 5 }, { name: "6A", value: 6 }
],
3: [
{ name: "7A", value: 7 }, { name: "8A", value: 8 }, { name: "9A", value: 9 }
]
},
2: {
1: [
{ name: "1B", value: 11 }, { name: "2B", value: 21 }, { name: "3B", value: 31 }
],
2: [
{ name: "4B", value: 41 }, { name: "5B", value: 51 }, { name: "6B", value: 61 }
],
3: [
{ name: "7B", value: 71 }, { name: "8B", value: 81 }, { name: "9B", value: 91 }
]
}
},
myDisableData: {}
From the mySelectionData object, we will build our myDisableData with this function:
setupMyDisableData() {
Object.keys(this.mySelectionData).forEach(parent_key => {
Object.assign(this.myDisableData, {[parent_key]: {}})
Object.keys(this.mySelectionData[parent_key]).forEach(child_key => {
Object.assign(this.myDisableData[parent_key], {[child_key]: true})
});
});
}
This will loop trough our "parents", assign their index to myDisableData and also loop trough the "childs" and assign their index to myDisableData with the "parent"-index as a pointer. After that we have a multi-layer object which is able to provide diabled= true or false for each selection.
The html for this example looks like this:
<div v-for="(item,index) in mySelectionData" :key="index">
<input type="number" v-model="myNumberInput[index]" #input="enableMySelection(index, myNumberInput[index])">
<div v-for="(child_item, child_index) in item" :key="child_index">
<select :disabled="myDisableData[index][child_index]">
<option v-for="(child_option, child_option_index) in child_item" :key="child_option_index" :value="child_option.value">{{child_option.name}}</option>
</select>
</div>
</div>
As I don´t use BootstrapVue, my html looks different, but I guess you will get the trick. You simply now refer to the three object by the index of "parent" and "child". In this example the function enableMySelection will enable a selection depending on the number entered in the input. The function looks like this:
enableMySelection(parent_index, input_number) {
Object.keys(this.myDisableData[parent_index]).forEach(child_key => {
this.myDisableData[parent_index][child_key] = true;
});
this.myDisableData[parent_index][input_number] = false;
}
So if you enter "2" in your first input, it will enable the second selection of the first block. If you enter 1 in the second input, it will enable the first selection in the second block.
As I said, this is just a generally example but this should be enough to help you define the structure to handle your multiple inputs and selections.
In my Vue/Nuxt project I have a form where the user can add update dynamic fields to be used in a price offer calculation.
When the form loads there will be created one field with the beforeMount lifecycle, and the user can then choose to create one or more extra fields.
in my data return I have this:
data() {
return {
calculationFields: { qty: 0, price: 3.86, selected: false },
}
}
And when the user click the "Add field" button the addField method is called:
addField() {
this.$store.dispatch('quantity/updateAdd', this.calculationFields)
},
where the updateAdd actions calls the UPDATE_ADD_ITEM mutation
UPDATE_ADD_ITEM(state, value) {
state.options.push(value)
},
value is { qty: 0, price: 3.86, selected: false }
this works fine as the options array is updated with the new field object
In the template I loop on this array to output X number of fields
<div v-for="(field, index) in getCalculationFields()" :key="field" class="flex-xs justify-between calculation-field">
<InputCustomPlaceholder type="number" :is-required="true" :input-id="`calculation-${index}`" :input-name="`calculation-${index}`" label-text="" placeholder-text="Add pieces" custom-placeholder-text="pcs" extraclass="flex-1 no-margin" />
×
</div>
My problem now is, that I can't figure out how I can use v-model on each dynamically created input fields so that I can update the qty value in the field object in the options state.
So if the list contains three fields like:
[
{ qty: 0, price: 3.86, selected: false },
{ qty: 0, price: 3.86, selected: false },
{ qty: 0, price: 3.86, selected: false }
]
So when the use in field number 2 input 200 as quantity the array will look like this:
[
{ qty: 0, price: 3.86, selected: false },
{ qty: 200, price: 3.86, selected: false },
{ qty: 0, price: 3.86, selected: false }
]
I believe I have to use something like
<InputCustomPlaceholder type="number" :is-required="true" :input-id="`calculation-${index}`" v-model="updateOptionList" :input-name="`calculation-${index}`" label-text="" placeholder-text="Add pieces" custom-placeholder-text="pcs" extraclass="flex-1 no-margin" />
But what is the best what to find the index of the field and update the value in that index on the array.
In a non-dynamic input I use something like this:
v-model="updateFieldOne"
updateFieldOne: {
set(value) {
this.$store.dispatch('fields/updatePartDimeWidth', value)
}
}
which works as intended.
You can give index props, and use it in mutation. EDIT_ITEM mutation help for edit item if you want add new elemenet use state.options.push(value).
this.$store.dispatch('fields/updatePartDimeWidth', {value ,index})
EDIT_ITEM(state, {value ,index }) {
state.options[i] = value
},
I have posted the same question on salesforce.stackexchange.com below is the link
https://salesforce.stackexchange.com/questions/283596/how-to-fetch-input-field-value-in-js-in-lwc?noredirect=1#comment426016_283596
But in the comments people suggested this is not much related to salesforce it is more of a Javascript thing so I am posting the same here, please take a look and suggest from html and js point of view.
HTML syntax seem different as it is lightning web component of salesoforce not angular, and also please help me to understand the same behavior in angular and I will do it in salesforce accordingly
in the below html code I am iterating 2 lists linItemData(11 records) and studyData(20 records)
<table class="slds-table slds-table_cell-buffer slds-table_bordered">
<thead>
<tr class="slds-line-height_reset">
<template if:true={studyData}>
<template for:each={studyData} for:item="sData">
<th key={sData}>
<div class="tablename slds-p-bottom_medium"></div>{sData.Visit_Name__c}
</th>
</template>
</template>
</tr>
</thead>
<tbody>
<template if:true={lineItemData}>
<template for:each={lineItemData} for:item="sLineItem">
<tr key={sLineItem}>
<template for:each={studyData} for:item="sData">
<td key={sData.Id}>
<lightning-input variant="label-hidden" class="fieldSize" type="number" step="0.01"
label="visitValue" data-key={sData.Id} onchange={visitValueChange} placeholder="00.00">
</lightning-input>
</td>
</template>
</tr>
</template>
</template>
</tbody>
</table>
and I am getting an expected result with all the required input fields on the UI like below:
now I need to fetch the input value for all v20s for example for v1 (first column name)should have array of 11 input records.
JS is as below:
visitValueChange(event) {
this.studyData
.find(item => item.Id === event.currentTarget.dataset.key)
.visitValue = event.target.value;
}
I have tried everything I could but the visitValue can hold only the 1 recent value for example if I add 1 on first input field, two on 2nd, three on 3rd and so on after that I hit a button which is calling a JS function to see the studyData array but it has only the recent value which is 3 not all 1,2 and 3 values entered and the requirement is to have an array of all the input values added on all the 11 input fileds for all the columns.
Please help me to suggest any workaround for the same.
You have two issues:
The way your data is designed
Linking the input with the correct record
Data model
Depending on your context, you could say that:
Each line is a record with columns being attributes of record (col1, col2, ...)
Each column is a record with lines being attributes of record (row1, row2, ...)
Each cell is a record identified with an id like x_y (1_1, 1_2, ...)
I would probably recommend option 1 as it's the most common representation.
This means you have to prepare / create records like this:
const myRecords = [
{
id: 1,
col1: 0,
col2: 0,
...
}, {
id: 2,
col1: 0,
col2: 0,
...
}
]
Linking input to correct record
Use LWC datatabel to create your table. You can then get what you need using custom data types. This would allow to use properly designed records (one by line and each columns is an attribute) without any transformation.
Display using the provided HTML
Unfortunatly there are some limits in Salesforce (with the HTML you provided) so you need to transform your records into this.
const myRecords = [
{
id: 1,
columns: [
{ id: 1, value: 0 },
{ id: 2, value: 0 }
...
]
}, {
id: 2,
columns: [
{ id: 1, value: 0 },
{ id: 2, value: 0 }
...
]
}
]
This will allow this to work
import {
LightningElement,
track
} from 'lwc';
export default class App extends LightningElement {
columns = [{
id: '1',
name: 'v1'
},
{
id: '2',
name: 'v2'
},
{
id: '3',
name: 'v3'
},
{
id: '4',
name: 'v4'
},
{
id: '5',
name: 'v5'
},
]
records = [{
id: '1',
columns: [{
id: '1',
value: 0
},
{
id: '2',
value: 0
},
{
id: '3',
value: 0
},
{
id: '4',
value: 0
},
{
id: '5',
value: 0
},
]
},
{
id: '2',
columns: [{
id: '1',
value: 0
},
{
id: '2',
value: 0
},
{
id: '3',
value: 0
},
{
id: '4',
value: 0
},
{
id: '5',
value: 0
},
]
}
]
visitValueChange(event) {
const recordId = event.target.dataset.recordId
const columnId = event.target.dataset.columnId
const value = event.target.value
const record = this.records.find(record => record.id === recordId)
const column = record.columns.find(column => column.id === columnId)
column.value = value
}
}
<template>
<table class="slds-table slds-table_cell-buffer slds-table_bordered">
<thead>
<tr class="slds-line-height_reset">
<template for:each={columns} for:item="column">
<th key={column.id}>{column.name}</th>
</template>
</tr>
</thead>
<tbody>
<template for:each={records} for:item="record">
<tr key={record.id}>
<template for:each={record.columns} for:item="column">
<td key={column.id}>
<lightning-input
variant="label-hidden"
class="fieldSize"
type="number"
step="0.01"
label="visitValue"
value={column.value}
data-record-id={record.id}
data-column-id={column.id}
onchange={visitValueChange}
placeholder="00.00"
></lightning-input>
</td>
</template>
</tr>
</template>
</tbody>
</table>
</template>
I have this code for view(model's value):
#foreach (var item in Model)
{
<input name="DepID" type="text" value="#item.DepID" id="id">
<input name="DepName" type="text" value="#item.DepName" id="depname">
<input name="DepID_Parent" type="text" value="#item.DepID_Parent"
id="parent">
}
on the other hand, I have an array like below in my script:
var testData = [
{ id: 1, name: 'my organization', parent: 0 },
{ id: 2, name: 'ceo office', parent: 1 },
{ id: 3, name: 'division 1', parent: 1 },
{ id: 4, name: 'division 2', parent: 1 },
{ id: 6, name: 'division 3', parent: 1 },
{ id: 7, name: 'division 4', parent: 1 },
{ id: 8, name: 'division 5', parent: 1 },
{ id: 5, name: 'sub division', parent: 3 },
];
I want to replace the value off all inputs to testData array, and use them in my script.
So,I change the definition of testData with this code for script:
var testData = $('#id,#depname,#parent').map(function () {
return testData.value;
}).get();
But when I replace testData with this code, the values aren't returned.
What changes must be done?
Your code has some issues. You are setting a static id attribute value to your input elements inside a loop. So when razor executes your code, it will generate markup for more than one input with the same id attribute value. That is invalid HTML! element Id's should be unique inside a document
From the comments you added to the question, you want to create a javascript array similar to what you have in testData variable, by reading the input values from your DOM. I suggest you wrap the inputs for each item in the collection, inside a wrapper div. You can use a jQuery selector on this wrapper div later to get the items to build your array. Make sure to remove the code which sets the same id attribute value inside the loop
#foreach (var item in Model)
{
<div class="item-row">
<input name="DepID" type="text" value="#item.DepID" />
<input name="DepName" type="text" value="#item.DepName" />
<input name="DepID_Parent" type="text" value="#item.DepID_Parent" />
</div>
}
Now in your javascript, get all the divs with item-row class, and get the inputs (using the name selector) and build the object with the 3 properties.
This should work
var testData = $("div.item-row").map(function () {
var t = $(this);
return {
id: t.find("[name='DepID']").val(),
name: t.find("[name='DepName']").val(),
parent: t.find("[name='DepID_Parent']").val()
};
}).get();
//testData is an array of js objects with 3 properties
console.log(testData);