I have a select dropdown:
<select class="form-control" id="teamSelect" [disabled]="!isSubmitButtonDisabled()" [(ngModel)]="selectedTeam" (ngModelChange)="onTeamChange($event)" style="width: 50%;">
<option *ngFor="let team of teams" [ngValue]="team">{{ team.text }}</option>
</select>
I populate it in ngOnit like this:
ngOnInit() {
this._microService.getTeams()
.subscribe(team => {
this.teams = team.map(m => { return { text: m.name, value: m.name } as Select; });
this.teams.unshift( { text: '', value: ''} as Select)
}
);
}
No problems!
Later I have button click that should add a new item to the dropdown...
onCreateTeam(team: string = ''): void {
if(team != '') {
let t = { text: team, value: team } as Select;
this.teams.push(t);
this.selectedTeam = t;
}
}
The dropdown gets populated but then I can't select anything. Is there a way to update the array in let team of teams from my component so the DOM gets the new option, and still allows a selection?
No errors are thrown in the Console.
Related
I am using a 'Custom Datatable' solution in order to modify picklist values within a datatable. Project code may be referenced here:
https://live.playg.app/play/picklist-in-lightning-datatable
I have made changes so that I can retrieve data from the custom object: Payment__c, and I am attempting modify the picklist values for the Payment_Status__c field. My 'debugging' method has been to create numerous console.log statements to verify data during the updating process. Picklist values are currently hardcoded (have not figured out how to dynamically pull from SF yet). Inline edit of individual cells works fine, and I am able to save those values as well (though changes are not reflected until I perform a manual page refresh). Picklist selection is working, but I am unable to save the currently selected picklist value in the datatable.
I believe that the intended trigger event for picklist selection changes--'valueselect', is not being fired, and the handleSelection method is not receiving this event when a new picklist selection is made.
The lightning component used on Salesforce is c-customDatatableDemo:
customDatatableDemo.js
import { LightningElement, track, wire } from 'lwc';
import getPayments from '#salesforce/apex/PaymentController.getPayments';
import saveRecords from '#salesforce/apex/PaymentController.saveRecords';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '#salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class CustomDatatableDemo extends LightningElement {
#track data = [];
//have this attribute to track data changed
//with custom picklist or custom lookup
#track draftValues = [];
#track lastSavedData = [];
connectedCallback() {
this.columns = [
{
label: 'Name',
fieldName: 'Name',
editable: false
}, {
label: 'Invoice Number',
fieldName: 'Invoice_Number__c',
editable: true
}, {
label: 'Invoice Amount',
fieldName: 'Invoice_Amount__c',
type: 'currency',
editable: true
}, {
label: 'Invoice Date',
fieldName: 'Invoice_Date__c',
type: 'date',
editable: true
}, {
label: 'Payment Status',
fieldName: 'Payment_Status__c',
type: 'picklist',
typeAttributes:
{
placeholder: 'Choose Status',
options: [
{ label: 'Needs to Be Paid', value: 'Needs to Be Paid' },
{ label: 'Issued', value: 'Issued' },
{ label: 'Voided', value: 'Voided' },
] // List of Payment Status picklist options
, value: {fieldName: 'Payment_Status__c' } // default value for picklist
, context: {fieldName: 'Id' } // binding Payment Id with context variable to be returned back
}
},
{
label: 'Description', fieldName: 'Work_Description__c', type: 'text', editable: true
}];
// Get Payments data
getPayments()
.then(result => {
this.data = result;
this.error = undefined;
})
.catch(error => {
this.error = error;
this.data = undefined;
})
// Save last saved copy
this.lastSavedData = JSON.parse(JSON.stringify(this.data));
}
updateDataValues(updateItem) {
console.log('START--updateDataValues()');
let copyData = [... this.data];
copyData.forEach(item => {
if (item.Id === updateItem.Id) {
for (let field in updateItem) {
console.log('updateDataValues() item.Id = ' + JSON.stringify(updateItem.Id));
console.log('updateItem[field] = ' + JSON.stringify(updateItem[field]));
item[field] = updateItem[field];
console.log('UPDATED--item[field] = ' + updateItem[field]);
}
}
});
//write changes back to original data
this.data = [...copyData];
console.log('this.data = ' + JSON.stringify(this.data));
let tempData = [...this.data];
//console.log('tempData = ' + JSON.stringify(tempData));
console.log('END--updateDataValues()');
}
updateDraftValues(updateItem) {
console.log('START--updateDraftValues()');
console.log('stringify draft updateItem = ' + JSON.stringify(updateItem));
let draftValueChanged = false;
let copyDraftValues = [...this.draftValues];
//store changed value to do operations
//on save. This will enable inline editing &
//show standard cancel & save button
let i = 0;
copyDraftValues.forEach(item => {
if (item.Id === updateItem.Id) {
i++;
console.log('i = ' + i);
for (let field in updateItem) {
console.log(i + '. UpdateDraftValues--item id if selected...item Id = ' + item.Id + ' & item value = ' + item.value);
item[field] = updateItem[field];
console.log('item[field] = ' + updateItem[field]);
}
draftValueChanged = true;
console.log('draftValueChanged = TRUE');
}
});
//draftValueChanged = true;
if (draftValueChanged) {
console.log('YESdraftValueChanged');
console.log('copyDraftValues = ' + JSON.stringify(copyDraftValues));
this.draftValues = [...copyDraftValues];
//console.log('draftValues = ' + JSON.stringify(draftValues));
} else {
console.log('NOdraftValue!Changed');
this.draftValues = [...copyDraftValues, updateItem];
let testDraftValues = {... this.draftValues};
console.log('JSON.stringify(testDraftValues) = ' + JSON.stringify(testDraftValues));
}
console.log('STOP--updateDraftValues()')
}
//listener handler to get the context and data
//updates datatable
picklistChanged(event) {
console.log('START--picklistChanged()');
console.log('EVENT type - ' + event.type);
event.stopPropagation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
console.log('picklistChanged()...updatedItem = ' + JSON.stringify(updatedItem));
this.updateDraftValues(updatedItem);
this.updateDataValues(updatedItem);
/* console.log('event.value = ' + event.value);
this.value = event.target.value;
event.stopPropagation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
console.log('updatedItem.context ' + updatedItem.context);
console.log('updatedItem.value ' + updatedItem.value);
console.log('updatedItem = ' + JSON.stringify(updatedItem));
this.updateDraftValues(updatedItem);
this.updateDataValues(updatedItem);
console.log('picklistChanged() = ' + JSON.stringify(updatedItem)); */
console.log('STOP--picklistChanged()');
}
handleSelection(event) {
console.log('START--handleSelection()');
this.updateDraftValues(event.detail.draftValues[0]);
console.log('this.updateDraftValues(event.detail.draftValues[0]);')
/* event.stopPropogation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
this.updateDraftValues(updatedItem);
this.updateDraftValues(updatedItem); */
console.log('STOP--handleSelection() = ' + JSON.stringify(updatedItem));
}
//handler to handle cell changes & update values in draft values
handleCellChange(event) {
console.log('START--handleCellChange()');
console.log('handleCellChange');
this.updateDraftValues(event.detail.draftValues[0]);
console.log('handleCellChange value = ' + JSON.stringify(this.updateDraftValues));
console.log('END--handleCellChange()');
}
handleSave(event) {
if (event.type === 'picklistchanged'){
}
console.log('START--handleSave');
console.log('Updated items = ', this.draftValues);
// save last saved copy
this.lastSavedData = JSON.parse(JSON.stringify(this.data));
console.log('this.lastSavedData = ' + JSON.stringify(this.lastSavedData));
this.fldsItemValues = event.detail.draftValues;
console.log('this.fldsItemValues = ' + JSON.stringify(this.fldsItemValues));
const inputsItems = this.fldsItemValues.slice().map(draft => {
const fields = Object.assign({}, draft);
console.log('JSON.stringify() fields ' + JSON.stringify(fields));
return { fields };
});
// Show toast after successful update
const promises = inputsItems.map(recordInput => updateRecord(recordInput));
Promise.all(promises).then(res => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
})
);
this.fldsItemValues = [];
return this.refresh();
}).catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: 'An Error Occured!!',
variant: 'error'
})
);
}).finally(() => {
// Clear draft values
this.draftValues = [];
});
// Refresh the window after successful save
//window.open('url','_self');
//document.location.reload(true);
//cmp.find("table-component-id").set("v.draftValues", null);
console.log('END--handleSave');
}
handleCancel(event) {
//remove draftValues & revert data changes
this.data = JSON.parse(JSON.stringify(this.lastSavedData));
this.draftValues = [];
}
async refresh() {
console.log('async refresh');
await refreshApex(this.data);
//this.connectedCallback();
}
}
customDatatableDemo.html
<template>
<lightning-card title="Invoicing" icon-name="custom:custom17">
<div class="slds-var-m-around_medium">
<template if:true={data}>
<c-custom-data-table
object-api-name="Payment__c"
key-field="Id"
data={data}
value=""
show-row-number-column
columns={columns}
onpicklistchanged={picklistChanged}
onvalueselect={handleSelection}
draft-values={draftValues}
oncellchange={handleCellChange}
onsave={handleSave}
oncancel={handleCancel}>
</c-custom-data-table>
<template if:true={data.error}></template>
</template>
</div>
</lightning-card>
<p>Selected value is: {value}</p>
</template>
customDataTable.js
import LightningDatatable from 'lightning/datatable';
//import the template so that it can be reused
import DatatablePicklistTemplate from './picklist-template.html';
import { loadStyle } from 'lightning/platformResourceLoader';
import CustomDataTableResource from '#salesforce/resourceUrl/CustomDataTable';
export default class CustomDataTable extends LightningDatatable {
static customTypes = {
picklist: {
template: DatatablePicklistTemplate,
typeAttributes: ['label', 'placeholder', 'options', 'value', 'context'],
},
};
constructor() {
super();
Promise.all([
loadStyle(this, CustomDataTableResource),
]).then(() => {})
}
}
picklist-template.html (Same folder as customDataTable)
<template>
<c-datatable-picklist label={typeAttributes.label} value={typeAttributes.value}
placeholder={typeAttributes.placeholder} options={typeAttributes.options} context={typeAttributes.context}>
</c-datatable-picklist>
</template>
datatablePicklist.js
import { LightningElement, api, track } from 'lwc';
export default class DatatablePicklist extends LightningElement {
#api label;
#api placeholder;
#api options;
#api value;
#api context;
handleChange(event) {
//show the selected value on UI
this.value = event.detail.value;
//fire event to send context and selected value to the data table
this.dispatchEvent(new CustomEvent('picklistchanged', {
composed: true,
bubbles: true,
cancelable: true,
detail: {
data: { context: this.context, value: this.value }
}
}));
}
}
datatablePicklist.html
<template>
<div class="picklist-container">
<lightning-combobox name="picklist" label={label} value={value} placeholder={placeholder} options={options}
onchange={handleChange}></lightning-combobox>}
</div>
</template>
lwcEditSaveRow.js
import { LightningElement, wire, track } from 'lwc';
import getAccounts from '#salesforce/apex/lwcEditSaveRowCtrl.getAccounts';
import { updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { refreshApex } from '#salesforce/apex';
const columns = [
{
label: 'Name',
fieldName: 'Name',
type: 'text',
}, {
label: 'Phone',
fieldName: 'Phone',
type: 'phone',
editable: true,
}, {
label: 'Industry',
fieldName: 'Industry',
type: 'text',
editable: true,
}, {
label: 'Type',
fieldName: 'Type',
type: 'text',
editable: true
}, {
label: 'Description',
fieldName: 'Type',
type: 'text',
editable: true
}
];
export default class LwcEditSaveRow extends LightningElement {
columns = columns;
#track accObj;
fldsItemValues = [];
#wire(getAccounts)
cons(result) {
this.accObj = result;
if (result.error) {
this.accObj = undefined;
}
};
saveHandleAction(event) {
this.fldsItemValues = event.detail.draftValues;
const inputsItems = this.fldsItemValues.slice().map(draft => {
const fields = Object.assign({}, draft);
return { fields };
});
const promises = inputsItems.map(recordInput => updateRecord(recordInput));
Promise.all(promises).then(res => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
})
);
this.fldsItemValues = [];
return this.refresh();
}).catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: 'An Error Occured!!',
variant: 'error'
})
);
}).finally(() => {
this.fldsItemValues = [];
});
}
async refresh() {
await refreshApex(this.accObj);
}
}
lwcEditSaveRow.html
<template>
<lightning-card>
<div class="slds-m-around_medium">
<h3 class="slds-text-heading_medium"><lightning-icon icon-name="custom:custom84" size="small"></lightning-icon> <strong style="color:#270086; font-size:13px; margin-right:5px;"> How to inline Edit/Save Rows With Lightning Datatable in Lightning Web Component (LWC) </strong></h3>
<br/><br/>
<template if:true={accObj.data}>
<lightning-datatable key-field="Id"
data={accObj.data}
columns={columns}
onsave={saveHandleAction}
draft-values={fldsItemValues}
hide-checkbox-column
show-row-number-column>
</lightning-datatable>
</template>
<br/>
<br/>
<!--Start RelatedTopics Section-->
<div style="border:1px #ddd solid; padding:10px; background:#eee; margin:40px 0;">
<p data-aura-rendered-by="435:0"><img src="https://www.w3web.net/wp-content/uploads/2021/05/thumbsUpLike.png" width="25" height="25" style="vertical-align:top; margin-right:10px;" data-aura-rendered-by="436:0"><strong data-aura-rendered-by="437:0"><span style="font-size:16px; font-style:italic; display:inline-block; margin-right:5px;">Don't forget to check out:-</span>An easy way to learn step-by-step online free Salesforce tutorial, To know more Click <span style="color:#ff8000; font-size:18px;" data-aura-rendered-by="442:0">Here..</span></strong></p>
<br/><br/>
<p data-aura-rendered-by="435:0"><img src="https://www.w3web.net/wp-content/uploads/2021/07/tickMarkIcon.png" width="25" height="25" style="vertical-align:top; margin-right:10px;" data-aura-rendered-by="436:0"><strong data-aura-rendered-by="437:0"><span style="font-size:17px; font-style:italic; display:inline-block; margin-right:5px; color:rgb(255 128 0);">You May Also Like →</span> </strong></p>
<div style="display:block; overflow:hidden;">
<div style="width: 50%; float:left; display:inline-block">
<ul style="list-style-type: square; font-size: 16px; margin: 0 0 0 54px; padding: 0;">
<li>How to get selected checkbox value in lwc</li>
<li>how to display account related contacts based on AccountId in lwc</li>
<li>how to create lightning datatable row actions in lwc</li>
<li>how to use if and else condition in lwc</li>
<li>how to display selected radio button value in lwc</li>
</ul>
</div>
<div style="width: 50%; float:left; display:inline-block">
<ul style="list-style-type: square; font-size: 16px; margin: 0 0 0 54px; padding: 0;">
<li>display account related contacts based on account name in lwc</li>
<li>how to insert a record of account Using apex class in LWC</li>
<li>how to get picklist values dynamically in lwc</li>
<li>how to edit/save row dynamically in lightning component</li>
<li>update parent field from child using apex trigger</li>
</ul>
</div>
<div style="clear:both;"></div>
<br/>
<div class="youtubeIcon">
<img src="https://www.w3web.net/wp-content/uploads/2021/11/youtubeIcon.png" width="25" height="25" style="vertical-align:top; margin-right:10px;"/> <strong>TechW3web:-</strong> To know more, Use this <span style="color: #ff8000; font-weight: bold;">Link</span>
</div>
</div>
</div>
<!--End RelatedTopics Section-->
</div>
</lightning-card>
</template>
Example of changing and saving non-picklist value in datatable:
Changing and saving non-picklist value
Example of changing and saving a picklist value:
Changing and saving picklist value (1)
Last bit of console output:
Changing and saving picklsit value (2)
As this is my first time working with Lightning Web components, I would greatly appreciate any assistance you may provide. Thanks in advance.
I was able to get this custom data table component working for something I am developing to effectively bind records as rows. Here 2 differences I notice:
I did not include onvalueselect and oncellchange methods for the component html declaration, only the onpicklistchanged.
You may want to use your custom server side controller method instead of the built-in uiRecordApi->updateRecord one. Something tells me this may not play nice with row data from the data table. In my implementation, I was simply able to pass the draftValues over to the server side method which has a single parameter of list of sObject:
async saveRecords(event){
const updatedFields = event.detail.draftValues;
this.draftValues = [];
this.showSpinner = true
try{
await saveRelatedRecords({sObjs: updatedFields}) // server side save
.then((result) => {
this.updateMessage = result;
})
this.showSpinner = false;
if(this.updateMessage == 'success'){
this.showToast('Success', 'Record(s) Updated', 'success');
} else{
this.showToast('Error', this.updateMessage, 'error');
}
await refreshApex(this._wiredRecordData);
this.unsavedData = this.records;
} catch (error) {
this.showSpinner = false;
this.showToast('Error while updating or refreshing records', error.body.message, 'error');
}
}
In regards to your data not refreshing, I suggest you wire your getPayments method so that you can always get a fresh set from the server side, rather than trying to keep track of and maintain data changes on the client side, something like:
_wiredRecordData;
#wire(getRelatedRecords)
relatedRecords(getRecsResult){
const { data, error } = getRecsResult;
this._wiredRecordData = getRecsResult;
if(data){
this.records = data;
}
}
Then after your success toast in your save method, you can use
await refreshApex(_wiredRecords); and lwc knows to rerender based on the wiring (or at least I think that's how it works.)
Lastly, here is the server side controller method I have to dynamically generate column header information so it does not need to be hard coded into the component. However I did need to modify the custom component a bit to include a new "fieldapi" attribute so that the client side method knows what field to set for the changed value during the onpicklistchanged action.
#AuraEnabled(cacheable=true)
public static String getColumnHeaders(String sObjAPI, String fieldAPIs)
{
List<ColumnHeaderInfo> colHeaders = new List<ColumnHeaderInfo>();
Schema.DescribeSObjectResult sObjDesc = Schema.getGlobalDescribe().get(sObjAPI).getDescribe();
Boolean objIsUpdateable = sObjDesc.isUpdateable();
Map<String, Schema.SObjectField> objFields = sObjDesc.fields.getMap();
for(String field: fieldAPIs.split(','))
{
if(!objFields.keySet().contains(field.toLowerCase())){
continue;
}
Schema.DescribeFieldResult fieldDesc = objFields.get(field).getDescribe();
if(!fieldDesc.isAccessible()){
continue;
}
ColumnHeaderInfo colHeader = new ColumnHeaderInfo();
colHeader.label = fieldDesc.getLabel();
colHeader.fieldName = fieldDesc.getName();
colHeader.editable = fieldDesc.isUpdateable() && sObjDesc.isUpdateable();
colHeader.type_x = fieldDesc.getType().name().toLowerCase();
if(colHeader.type_x == 'picklist')
{
colHeader.type_x = 'picklist';
List<Schema.PicklistEntry> picklistValues = fieldDesc.getPicklistValues();
colHeader.typeAttributes = new TypeAttributes();
colHeader.typeAttributes.options = new List<Option>();
for(Schema.PicklistEntry ple: picklistValues)
{
Option opt = new Option();
opt.value = ple.getValue();
opt.label = ple.getLabel();
colHeader.typeAttributes.options.add(opt);
}
colHeader.typeAttributes.context = new FieldName();
colHeader.typeAttributes.context.fieldName = 'Id';
colHeader.typeAttributes.value = new FieldName();
colHeader.typeAttributes.value.fieldName = fieldDesc.getName();
colHeader.typeAttributes.fieldapi = fieldDesc.getName();
}
// multi-select picklist fields not supported so make them read-only
if(colHeader.type_x == 'multipicklist'){
colHeader.editable = false;
}
colHeaders.add(colHeader);
}
return JSON.serialize(colHeaders).replaceAll('type_x', 'type');
}
private class ColumnHeaderInfo
{
public String label;
public String fieldName;
public String type_x;
public Boolean editable;
public TypeAttributes typeAttributes;
}
private class TypeAttributes
{
public String placeholder;
public List<Option> options;
public FieldName value;
public FieldName context;
public FieldName label;
public FieldName tooltip;
public String fieldapi;
public String target;
}
private class Option
{
public String label;
public String value;
}
private class FieldName
{
public String fieldName;
}
This is an example of my database
I am making a website using nodejs, MongoDB, and pug. I have displayed this data in a pug form with the data in the select boxes. Like this but in pug using for loops and all the data-
<!DOCTYPE html>
<html>
<body>
<form>
<select name="Type">
<option value="Electronic">Electronic</option>
</select>
<select name="Brands">
<option value="Apple">Apple</option>
<option value="Dell">Dell</option>
<option value="Samsung">Samsung</option>
</select>
<select name="Products">
<option value="Macbook Pro">Macbook Pro</option>
<option value="Inspioren">Inspioren</option>
<option value="Galaxy S20">Galaxy S20</option>
</select>
</form>
</body>
</html>
What I want to do is, change the select box options based on what the user has selected in other select options.
For example:- If a user selects "Type: "Electronic", and "Brand: Apple",I want to display only Apple products as the options.
Or if a user selects "Type: "Electronic" it should automaticly display brands list in the select box for brands.
The data will be added from the database (it will not be hardcodded).
One possibility could be to modify your Pug view to include select tag id's and leave the downstream selects blank and then add a script at the end of your view to add event listeners and do some DOM manipulation using JQuery or just javascript after the view is loaded. The event handlers would then allow you to conditionally fill in your next select tag based on whatever you choose in the current tag.
Something along the lines of:
script.
document.addEventListener("DOMContentLoaded",
function(e) {
const typeSelect = document.getElementById('type')
typeSelect.onchange = function(e) {
const brandSelect = document.getElementById('brand')
if (typeSelect.options[typeSelect.selectedIndex].text === 'Apple') {
['MacBook Pro', 'MacBook Air', 'MacBook Mini'].forEach(function(product) {
let newOption = createElement('option')
newOption.textContent = product
brandSelect.appendChild(newOption
}
else if ( // etc... ) {}
else {
// functionality to clear out the downstream select tags.
}
}
const brandSelect = document.getElementById('brand')
brandSelect.onchange = // etc, etc....
})
Server side code, with some test data:
app.get("/avi", (req, res) => {
res.render("avi", { Types: [ "Electronic"], data:
[ { Type: "Electronic", Brand: "Apple", Products: [ "MacBook Pro", "MacBook Air", "Mac Mini"]},
{ Type: "Electronic", Brand: "Dell", Products: [ "Inspioren", "Latitude"]},
{ Type: "Electronic", Brand: "Samsung", Products: [ "Galaxy S20", "Galaxy S10"]}
]
});
});
You should include a Types list, otherwise your Pug script will have to go through the raw data to identify the number of unique Types.
avi.pug:
html
head
body
p Linked Dropdowns
form
p Type:
select#types(onchange="typeChanged()")
option(value="") Select Type
each item of Types
option(value=item)=item
p Brand:
select#brands(onchange="brandChanged()")
option(value="") Select Brand
p Product:
select#products()
option(value="") Select Product
script.
const data = JSON.parse(`!{JSON.stringify(data)}`);
const types = document.getElementById("types")
const brands = document.getElementById("brands")
const products = document.getElementById("products")
const typeChanged = () => {
clearBrands(); clearProducts();
if (types.selectedIndex!==0) {
const selectedType = types.options[types.selectedIndex].text;
data.forEach(d => {
if (d.Type===selectedType) {
const newBrand = document.createElement("option")
newBrand.value = newBrand.innerText = d.Brand;
brands.appendChild(newBrand);
}
});
}
}
const brandChanged = () => {
clearProducts();
if (brands.selectedIndex!==0) {
const selectedType = types.options[types.selectedIndex].text;
const selectedBrand = brands.options[brands.selectedIndex].text;
data.forEach(d => {
if (d.Type===selectedType && d.Brand===selectedBrand) {
d.Products.forEach(p => {
const newProd = document.createElement("option")
newProd.value = newProd.innerText = p;
products.appendChild(newProd);
});
}
})
}
}
const clearBrands = () => {
const item0 = brands.childNodes[0];
brands.textContent = "";
brands.appendChild(item0);
}
const clearProducts = () => {
const item0 = products.childNodes[0];
products.textContent = "";
products.appendChild(item0);
}
The data at the server is injected into the client side Javascript with:
const data = JSON.parse(`!{JSON.stringify(data)}`);
This method is not very robust. There will be problems if anywhere in the data there is a backtick ` character.
I am answering my own question here. What I did was add the onchange function on the Type select box. And created a script inside my file, with the following code-
function change() {
var Type_name = document.getElementById("type").value;
var Brand= document.getElementById('brands');
var Product = document.getElementById('products');
Brand.options.length = 0;
Product.options.length = 0;
var DefaultBrand = new Option("Brand", "Null");
var DefaultProduct = new Option ("Product", "Null");
Brand.add(DefaultBrand, undefined);
Product.add(DefaultProduct, undefined);
var product_master = !{JSON.stringify(product_names)};
for (const brands of product_master) {
if (brands.Type == Type_name){
const BrandOption = new Option(brands.Brand, brands.Brand);
Brand.add(BrandOption, undefined);
}
}
And another function similar to this to add products.
This worked for me. But if anyone wants to improve this code, I would appreciate the help.
I am using angular2-multiselect-dropdown. Whenever I click "SelectAll" in the dropdown, it doesnt select all because it is also emiting deSelectAll event and so it also calls onDeSelectAll() function. And so its not implementing the default functionality of selecting all the items in the dropdown. Select All checkbox is also not checked. Please tell me how can I make this work, as I have a deadline soon.
ts:
ngOnInit() {
this.dropdownList = [
{ id: 1, itemName: "Pacemaker1", value: "Pacemaker1" },
{ id: 2, itemName: "Pacemaker2", value: "Pacemaker2" },
{ id: 4, itemName: "Pacemaker2", value: "Pacemaker2" },
];
this.selectedItems = [];
this.dropdownSettings = {
singleSelection: false,
text: "Select devices",
selectAllText: "Select All",
unSelectAllText: "UnSelect All",
enableSearchFilter: true,
badgeShowLimit: 3,
};
this.getStudies();
}
onItemSelect(item: any) {
this.selectedItems.push(item);
}
OnItemDeSelect(item: any) {
this.selectedItems = this.selectedItems.filter((el) => el.id !== item.id);
}
onSelectAll(items: any) {
console.log("select", items);
this.selectedItems = [];
this.selectedItems.push(items);
}
onDeSelectAll(items: any) {
console.log("deselect", items);
this.selectedItems = [];
}
html:
<div class="form-group">
<label class="form-col-form-label">
Associated Devices
</label>
<angular2-multiselect
class="form-control"
[data]="dropdownList"
[settings]="dropdownSettings"
(onSelect)="onItemSelect($event)"
(onDeSelect)="OnItemDeSelect($event)"
(onSelectAll)="onSelectAll($event)"
(onDeSelectAll)="onDeSelectAll($event)"
formControlName="associatedDevices">
</angular2-multiselect>
</div>
Please check the replicated functionality here
https://stackblitz.com/edit/angular-ivy-esame2?file=src%2Fapp%2Fapp.component.html
I solved this issue by installing #4.6.3 version and its working fine. Apparently its an open issue in the package itself.
I faced the same issue you can solve it by CSS like this
label[for=selectAll] {
pointer-events:none;
}
I am calling service in Angular7 at every dropdown option change. But when I change selected option on dropdown I am getting getAllByCountryId of undefined error.
Here is function that calling http service:
countryOnChange(countryId: Guid) {
this.cityService.getAllByCountryId(countryId).subscribe(
res => {
if (res.code === ResponseCode.success) {
res.dataList.map(item => {
this.cities.push({
value: item.id.toString(),
label: item.dataValue
});
});
if (this.formComponent !== undefined) {
this.formComponent.form.controls['cityId'].patchValue(this.cities);
}
}
},
err => {
this.error = true;
});
}
Here is the HTML code that calling above function on every dropdown option change:
<ng-container *ngSwitchCase="'dropdown'" class="col-md-12">
<ng-select [ngClass]="'ng-select'" [options]="input.options" [formControlName]="input.key" [id]="input.key" (selected)="input.onChange($event.value)"></ng-select>
</ng-container>
input.onChange($event.value) and countryOnChange is connected at the backend.
Here is how to call countryOnChange function:
const dropdown2 = new InputDropdown({
key: 'countryId',
label: '',
onChange: this.countryOnChange,
options: this.countries,
value: '',
required: true,
order: 3
});
Error http://prntscr.com/ovjxe7
How can I solve this problem?
I think [ngModel] is needed:
<select [ngModel]="selectedValue" (ngModelChange)="onDropdownChange($event)"
class="form-control">
<option *ngFor="let category of categorylist" [ngValue]="category.id">
{{category.Description}}</option>
</select>
refer to: Angular 2 How to bind selected id in Dropdownlist with model?
getAllByCountryId of undefined error means you are getting this.cityService as undefined.
Check with which this context your function is binding when you are creating the InputDropDown. May be you need to define it like :-
const dropdown2 = new InputDropdown({
key: 'countryId',
label: '',
onChange: this.countryOnChange.bind(this),
options: this.countries.bind(this),
value: '',
required: true,
order: 3
});
Hope this helps.
I'm developing a category selection template with pass in the previous selection.
But the select Only works on "on first loading" if I change the select so I get behavior error. (this unselect the parent)
I need a "light".
This is the link of project
https://zimeonline.com.br
I try changer the object vue data() in each ajax in my components
<template>
<div>
<select #change="category()" v-model="selectedId" v-bind:key="option[0].id" v-for="option in options" class="browser-default custom-select">
<option v-bind:value="op.id" v-bind:selected="op.selected==1" v-bind:key="op.id" v-for="op in option">{{op.name}}</option>
</select>
</div>
</template>
<script>
export default {
name: "ProductFormCategory",
data() {
return {
options: {},
selectedId:''
}
},
created() {
let vm = this;
vm.category();
},
methods: {
async category() {
let vm = this;
await vm.$http.get('category/'+vm.selectedId).then(function (response) {
vm.options = response.data;
}).catch(function () {
});
vm.$forceUpdate();
},
}
}
</script>
<style scoped>
.browser-default{
margin-bottom: 10px !important;
}
</style>
this URL list ALL FATHER categorys
https://api.zimeonline.com.br/api/category
this URL list ALL CHILDREN categorys
https://api.zimeonline.com.br/api/category/some_id(from father category)
exemple: https://api.zimeonline.com.br/api/category/5
Then 5 is ID from https://api.zimeonline.com.br/api/category
here an exemple of the atual code select
https://zimeonline.com.br (a litle slow in the fist time)
I'm not sure that I understand your questions. But I see some problems in your code:
Why did you put a v-for in both select and option?
In the first loop, you bind a key to option[0] instead of options[0] or option
Also a tip: You could use vm.$set to make reactive variables
Solution for category basead from parent id with select input option sub-menu
<script>
export default {
name: "ProductFormCategory",
props:{
setCategoryId:String
},
data() {
return {
options: {},
categoryId: ''
}
},
created() {
let vm = this;
vm.categoryId = vm.setCategoryId || ('');
vm.category();
},
methods: {
async category(event) {
let vm = this;
if (event) {
vm.categoryId = (event.target.value);
}
await vm.$http.get('category/' + vm.categoryId).then(function (response) {
vm.options = response.data;
}).catch(function () {
});
},
}
}
<template>
<div>
<select
#change="category($event)"
v-bind:key="option[0].id"
v-for="option in options"
class="browser-default custom-select">
<option value="">Selecione uma categoria</option>
<option
v-bind:value="op.id"
v-bind:selected="op.selected==1"
v-bind:key="op.id"
v-for="op in option">
{{op.name}}
</option>
</select>
</div>