I want to add a comboBox or menu button to my interface which will have data in it that comes from an array. The data in the array won't always be the same so I need the button to be "dynamic". How can I achieve that ? I can't specify a model if the array changes...
Edit: I'm using ExtJS 6, so I need to be able to feed the menu parameter:
menu: [{
text:'Menu Item 1'
},{
text:'Menu Item 2'
},{
text:'Menu Item 3'
}]
Example:
1) Users selects a menu item and click on a send button.
2) Depending on the value of the item the user clicked on, a javascript array is created with sometimes 2, sometimes 10 fields in it.
3) The fields are shown in a new menu button or combobox.
Thanks for your help !
HTML
<input type="text" name="example" list="exampleList">
<datalist id="exampleList">
<option value="A">A</option>
<option value="B">B</option>
</datalist>
Javascript
function generateOptionsFromDynamicArray (arr) {
// Get the datalist by id, cache option variable
var datalist = document.querySelector('#exampleList'),
option;
// Remove old options
while( datalist.firstChild ) {
datalist.removeChild(datalist.firstChild);
}
// Loop through array
for (var i = 0, l = arr.length; i < l; ++i) {
option = document.createElement('option');
option.setAttribute('value', arr[i]);
option.innerText = arr[i];
datalist.appendChild(option);
}
}
I created a function that you can pass that dynamic array into in order to update the combobox, in this case I'm using a datalist.
A few points about this code, you should add a check to ensure arr is an array or "array-like" (typedarrays I'm looking at you). You should also remove the datalist from the DOM while these changes are happening so you dont redraw the DOM on each iteration
I've created a fiddle for testing.
You cannot listen to an array change event, so whenever you change the array, you would also have to call following function:
function arrayToStore(array) {
var store = Ext.getCmp("myComboId").getStore();
//var store = Ext.getStore("myComboStore");
store.removeAll();
store.add(array.map(function(item) {
// This maps the array entry into a model you can add to the store.
// Instead of "field1", use your field name.
// If your array contains an object, you can preprocess it here.
// "field1" would be the default value if you have defined
// an implicit store by providing an array in the combo config:
// store:['item1','item2','item3'],
return {
field1:item
};
});
}
Related
I am trying to add dropdown items and handle the click based on the string value of the dropdown item. When I do console.log(props.storedSections[x]), it logs the correct value for the string. However when I try to use it to store the string in to check in handleSectionClick, it is just left as undefined and I have tried wrapping it in {}, {}, and ${}, but none of it works as I intend it to. Any ideas? Also it is a useState variable that is passed down from a parent component but that shouldn't matter since it displays properly when console logged.
here is the declaration of the sections useState object
const [sections, setSections] = useState([<Dropdown.Item onClick={()=>handleSectionClick("Work")}>Work</Dropdown.Item>])
Here is the useEffect function I am using to take the sections variable and add extra items to it using the strings stored in the storedSections useState variable
useEffect(() =>{
//gets the new list without the Add New object
let newSectionList = [...sections.slice(0, sections.length-1)]
for(var x = 0; x < props.storedSections.length; x++){
if(sections.indexOf(props.storedSections[x]) == -1)
//adds the new object that they want to add
newSectionList.push(<Dropdown.Item onClick={()=>handleSectionClick(props.storedSections[x])}>{props.storedSections[x]}</Dropdown.Item>)
}
//then adds in the Add new object again
newSectionList.push(<Dropdown.Item onClick={()=>handleSectionClick("Add New")}>Add New</Dropdown.Item>)
setSections[newSectionList]
setNewSectionTest(newSectionList)
}, [])
Here is the code for handleSectionClick. If I console log the values here they are undefined.
function handleSectionClick(item) {
//if they select the Add New section from the dropdown then bring up the option to type a new one
if (item === "Add New") {
setNewSection(true)
}
//updates the header for the dropdown and keeps track of which section should be saved for the task
else{
setCurrentSection(item)
}
}
In my App.jsx I declare the storedSections like this
const [storedSections, setStoredSections] = useState(['test1', 'test2'])
The main goal of what I am trying to do is to take a dropdown menu with preset items in it, give the user the ability to add their own custom options to the dropdown menu and have the new values persist on a rerender. I plan to move this to a more complicated format including a database that stores each users custom dropdowns, but for now I am just confused why the value is stored properly and is console logged properly but when I try to use it in the declaration of the Dropdown Item, it reads as undefined.
one very obvious problem is var x = 0 in for loop, try changing it to let x = 0; as in below code, and also add dependent props in useEffect dependency array
e.g. useEffect(() => {}, []) here in [] add props.storedSections and sections if it is also coming from props, also handleSectionClick if is hooks returned function
useEffect(() =>{
//gets the new list without the Add New object
let newSectionList = [...sections.slice(0, sections.length-1)]
for(let x = 0; x < props.storedSections.length; x++){
if(sections.indexOf(props.storedSections[x]) == -1)
//adds the new object that they want to add
newSectionList.push(<Dropdown.Item onClick={()=>handleSectionClick(props.storedSections[x])}>{props.storedSections[x]}</Dropdown.Item>)
}
//then adds in the Add new object again
newSectionList.push(<Dropdown.Item onClick={()=>handleSectionClick("Add New")}>Add New</Dropdown.Item>)
setSections[newSectionList]
setNewSectionTest(newSectionList)
}, [props.storedSections, sections])
I wrote this function to filter by status type. It's working but every time I filter the table data rows get disappeared. There're two status ( Active and Completed ) I wrote this code for filter,
<div class="DropContent">
<label class="LabelView">Status</label><br />
<select class="dropdown-size form-control" v-model="ins_status" v-on:change="filterData">
<option v-for="(option, i) in optionFilter" :value="i">
{{ option }}
</option>
</select>
</div>
filterData(evt) {
var val = evt.target.value;
if(val==0){
this.inspections = this.inspections.filter(function(e){return e.status = "Scheduled"});
}if(val==1){
this.inspections = this.inspections.filter(function(e){return e.status != "Scheduled"});
}
},
This is the array that load data to table from a for loop,
Also inside 0: Object There's another array which contains data like above objects from the screenshot
So totally there're 3 rows for the table. Before calling filter function, all 3 rows are visible. but when I filter again and again it reduces the no of rows of the table. According to given data if I filter three times no table records are shown in the table. Help me thanks.
try to store this.inspections in a local variable and then filter that variable and store the result inside this.inspections.
filterData(evt) {
var val = evt.target.value;
var inspections = this.inspections; // save inspections in local variable
if(val==0){
this.inspections = inspections.filter(function(e){return e.status = "Scheduled"});
} if(val==1){
this.inspections = inspections.filter(function(e){return e.status != "Scheduled"});
}
}
The problem was I modified the existing array. So each time I filter it changes. which means it changes the original table data even I assign it to a local variable. So I passed an extra prop to my working component and assigned it to a local variable.
I am working on an array, Actually, I have a dropdown list. I am pushing that object into an array but I am facing one issue actually when I select something it shows two elements at the same time like in dropdown let suppose if I have options ( option1, option2, option3). For example, I have selected option1 it pushed object value as option1 but when I select option2 it also pushed it into an array. I want unique values like if I select options2 it should be select recent value.
generateExtraFieldData = (data, name, index, type, value, values) => {
const { projectFloorData, unitModifiedData } = this.state
let obj = projectFloorData[name]
obj['data'] = data
let tempArr = [...unitModifiedData]
tempArr.push(obj)
this.setState({ unitModifiedData: this.uniqueFiles(tempArr) })
// projectFloorData[name].data = data
}
uniqueFiles = (data) => {
let unique = _.uniqBy(data, 'index')
console.log('## array', unique)
return unique
}
I have used lodash but it just return ist selected value, I need a recent value like if the user selected a second time
Try using yourArray.length = 1;, this limit you array to an int limit. And if you select another option, just do yourArray.length = 0 to clear the array and then again yourArray.length = 1; to store the new option.
why are you pushing your selected value into your array if you want to select a single value at a time try an object instead of an array and change the value/ reassign the value on selection.
I am trying to fetch a set of objects from a server and add their attributes as options to a datalist element whenever a user clicks on the input field. I want to display unique options in the list only, however, anytime the input field comes into focus, my code will keep adding every option to the datalist even though I am making a check for it not to do so.
<form action="">
<label for="">Step 1: Select or create a theme: </label>
<input type="input" list="themes" name="themes" onfocus="fetchThemes()" />
<datalist id="themes">
</datalist>
</form>
<script>
let host = "http://localhost:3002"
function fetchThemes(){
fetch(host + "/contents")
.then((response) => response.json())
.then((data) => addToDatalist(data))
}
function addToDatalist(data){
let datalist = document.getElementById('themes');
for (let object of data){
let option = document.createElement("option")
option.value = object.name
if (datalist.contains(option) === false){
datalist.appendChild(option)
}
}
console.log(document.getElementById('themes'))
}
</script>
I know i'm missing something small, but im not sure what it is that i'm doing wrong. Are DOM elements similar to objects in Python or Java, where even though two objects can have the same values, they're considered different since they are stored in separate memory locations? How can I go about fixing this?
i have made two arrays, first one is the check the array which contains all the unique values and the second one is the response of the server "object".
here i am comparing all the values of the check array with the one value of the object to get the unique value !!!
i hope this helps you !!!
//consider object as an array of the options and you want to include only the unique one
var check = []
var object = []
for(const i=0;i<=object.length;i++)
{
for(const j=0;j<=check.length;j++)
{
if(check[j] ===option[i])
{
console.log("Value exists")
}
else{
option.value = check[j]
}
}
}
for(const i=0;i<=check.length;i++)
{
option.value = check[i]
}
I'm trying to have 4 sub fields, billing code, channel, subject code and name, autopopulate certain values based on the answer of their parent field, Event Type. In other words, if the answer to event type is "A", dropdown fields will appear for each sub field based on "A".
Let's say the first select-element of the document has the values
'Plant', 'Animal' and 'Ghost' and the next select-element should change
when the selected value of first ele changes, then this is how we do it:
var majorField = document.getElementsByTagName('select')[0]
var minorField = document.getElementsByTagName('select')[1]
// Define a dict, mapping each possible value to a function:
majorField.onChangeMap = {
Plant: function() { minorField.innerHTML = '<option>Cocoa</option><option>Cocos</option>' },
Animal: function() { minorField.innerHTML = '<option>Cat</option><option>Cow</option>' },
Ghost: function() { minorField.style.visibility = 'hidden' },
}
// When value changes, execute function of dict-map:
majorField.onchange = function(event) {
event.target.onChangeMap[event.target.value]()
}
// Make sure he minor-field has initially the correct state, by
// executing the mapped function for the major-field's current-value:
majorField.onChangeMap[majorField.value]()
Note that this is a very minimal illustration-example for the mapping only, as
one wouldn't set the options as an html-string, and hiding the minorField on
Ghost should be reversed on all other options with visibility = 'visible', here.