Quasar QSelect with multiselect, does not show async selected values - javascript

I am using latest quasar (1.15.3).
I have a QSelect component with multiselect set to true
and i'm getting data from the server. I expect the multi select to be updated with the selected values, but it only happens when I click it.
Here is the select code:
<q-select
v-model="form.scopes"
ref="scopesSelect"
required
class="q-mt-md full-width"
label="Role Application Scopes"
placeholder="Select one or more application scope(s)"
data-testid="scope-select"
option-value="value"
option-label="label"
multiple
emit-value
use-input
use-chips
:options="filteredScopes"
:rules="[
val => (val && val.length) || 'Role Application scope is required'
]"
#filter="onFilterByScope"
/>
form.scopes contains ["Global","Default"] so I expect these values to show as selected.
filteredScopes has this form:
[
{label: "Global", value:"Global"}
...
]
This is how the page looks after I loaded the data from the server:
as you can see, the last select is not populated, but as soon as I click it, It show the selected values:
Currently the only way I found around it is by using an ugly hack:
hackToCauseMultiselectListToRenderSelectedValues() {
this.$nextTick(() => {
this.$refs.scopesSelect.focus();
});
setTimeout(() => this.$refs.roleName.focus(), 500);
},
So I'm manually focusing the select component, which also shows the dropdown, and then, after a while I focus the input at the top so the dropdown will go away.
I tried other methods like this.$refs.scopesSelect.refresh(); but nothing worked :(
Would love to hear any idea.

Related

TypeaHead onChange fires before value is updated when clicked

The following gif should show the problem in action.
Typeahead seems to trigger the onChange function before actually setting the value from a click, for who knows what reason.
As you can see whatever is typed into the box is grabbed correctly, but if a user selects an option from the dropdown only what had been typed in up to that point is grabbed, rather than the appropriate behavior which is the value in the text-box.
The TypeAhead JS code looks like
$('#typeahead_id').typeahead({
name: 'typeahead',
remote: 'search.php?key=%QUERY,
limit: 10
});
And the html for the input
<label>Team Name:</label>
<input type='text' id='typeahead_id' onChange='update_params("team",typeahead_id)' class='typeahead tt-query' autocomplete='on' spellcheck='false' placeholder='Select Team'><br>`;
The update Param method
function update_params(val, id) {
let temp = nodes[id]
temp.params[val] = $("#" + val + id).val()
console.log(temp)
}
The oddness of this can be explained in that each of the blue boxes is referred to as a node, and can have their own unique typeahead.
I need a way in that users can type the name of the team into the input or select one from the dropdown and my code should be able to retrieve that value and set it in the appropriate spot.

Cypress unable to select multiselect with loop

I am writing a React application that I'm testing with Cypress. In my integration tests I've written a cypress command that takes an array of strings, in order to select items in a multi-value select box.
The code I'm using looks roughly like this:
Cypress.Commands.add("command", (options) => {
options.forEach((option) => {
cy.get("div[data-g-portal-id='1']") // this is the container for the select box dropdown
.find("div[role='menubar']")
.contains(option)
.click({ force: true });
});
}
I've tried various iterations of this, including things like cy.wrap and .each. Whatever I do, when the array contains more than one item, it clicks one item, the item is marked as selected successfully, then it clicks the other item, marks it as selected, but the first item loses its selection state. Its as if the internal state of the component never really got the initial change.
I've confirmed this is not a bug in my application; when testing it manually, the multi-select works fine. But Cypress just doesn't want to know. Any help would be much appreciated.
The v2.grommet.io/select uses a "portal" to display the dropdown options.
The portal is just a div that's appended to body when the dropdown opened and removed again when an option is clicked.
Problem is, there isn't a property to connect the dropdown and portal containing the options. There may be other portals present e.g the Layer component uses a portal.
The options portal we need to target will always be the last portal on the page (since we just opened the dropdown). In the custom command, applying the .last() command will select the options portal.
Cypress.Commands.add("multiselect", (options) => {
options.forEach((option) => {
cy.get(`[data-g-portal-id]`)
.last() // just opened the dropdown so option are in the last portal
.find("div[role='menubar']")
.contains(option)
.click();
});
});
cy.get('input[name="my-select"]')
.click(); // open dropdown
.multiselect(['First', 'Third']);
cy.get('input[name="my-select"]')
.click(); // close dropdown
cy.get('input[name="my-select"]')
.should('have.value', 'multiple')
The test ends with dropdown displaying the text "multiple".
Configuration of the Select,
<Select
multiple // allow multiple selected options
closeOnChange={false} // do not close the dropdown between selections
name="my-select"
options={myOptions}
...
/>

Selected value from semantic ui react dropdown not appearing when selected

I can't get the selected value from the dropdown to render inside the dropdown once it's selected.
The right value is being set (seen via console) but isn't displayed inside the actual dropdown
const onSlotIdChange = (e, data) => {
console.log(props);
console.log("slotId fired, value ---> ", data.value);
props.setFieldValue("slotId", data.value);
};
The actual component is here
<Dropdown
id="slotId"
value={slotId}
onChange={onSlotIdChange}
options={slotIds.map(id => {
return {
key: id.id,
text: id.id,
value: id.id
};
})}
/>
I've had an issue exactly like this and the solution before was to use something like props.setFieldValue("slotId", e.currentTarget.textContent); but i've tried this and it isn't working in this case. The <Dropdown> component is from Semantic ui react
I have a codesandbox here. Once you get to the splash page go to the Login page via the button at the top. Select Slot Sec officer from the radio group it will render 3 dropdowns, the 2nd and 3rd dropdowns (slotId and deviceId) are where I'm having the issue. If you pull up the console and make a selection the value is getting set correctly but the value doesn't appear in the dropdown once it's selected.
The code for the dropdowns are in getSlotIds and getDeviceIds classes. and the onChange methods are inside FormikLoginForm class
It's because you're not setting the state after the user select the value, like you did in "Slot Security Officer Role" (this is correct, see line 246 in your codesandbox).
For example, to fix "device id" dropdown, after line 258, I put this code in line 259:
this.setState({deviceId: data.value});
and it works. The same need to be done for slotId, after line 253:
this.setState({slotId: data.value});

Why is the title (a string) of my v-select being broken into newlines at the spaces?

The v-select v-model value is broken into new lines at spaces when user clicks to open dropdown.
I have tried styling (white-space) to solve the issue. I've also tried changing the string to an array and looping through the array but that seems like overkill. I am using JS, https://vue-select.org/ and Vue. I am not using Vuetify's v-select.
My data:
data: () => ({
selectedTitle: "Job Title"
}),
The v-select:
<v-select
class="job-title-select"
:options="titles"
v-model="selectedTitle"
#change="(entry) => this.updateCriteria(entry, 'Job Title')"
taggable/>
Note: updateCriteria() is sending data to the store. It doesn't affect the v-select display or local value changes. v-model does.
Expected: I should see the value as "Job Title", "Director of Stuff", on one line when the user clicks on the v-select.
Outcome: When user expands/clicks on dropdown, this is what appears as the title for the dropdown element (these are not dropdown items):
Job
Title
Director
Of
Stuff
It turns out that vue-select has conflicts with Bulma. I removed Bulma as a dependency and everything was fine.
https://github.com/sagalbot/vue-select/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aclosed+bulma

Meteor Select Box - mark option as selected depending on data context

I have been trying to figure out how to set the 'selected' attribute on an option within a select box and have fallen short today. Any help would be appreciated.
What I'm trying to accomplish:
When a user chooses an option and hits submit, the data saves to a new mongo document and the new entry is shown on the screen (this part works). Upon browser refresh, the state is lost (due to no selected attribute being set) and the select box goes back to the first option. I need to figure out how to set the selected state depending on the value the user has saved on that particular document. On this page there are many of the same select boxes allowing the user to choose different options for other entries.
References (tried to implement with no luck):
Check for equality in Spacebars?
https://github.com/meteor/meteor/wiki/Using-Blaze#conditional-attributes-with-no-value-eg-checked-selected
How do I indicate 'checked' or 'selected' state for input controls in Meteor (with spacebars templates)?
select box template:
<template name="tEdit">
<div class="form-group">
<div class="controls">
{{> fFEdit}}
</div>
</div>
</template>
select box option template:
<template name="fFEdit">
<select class="form-control" name="fFSelect">
{{#each fFSelect}}
<option value="{{fId}}">{{fF}}</option>
{{/each}}
</select>
</template>
setting data context
Template.fFEdit.helpers({
fFSelect: function() {
var fFArray = [
{ fF: "foo", fId: 0 },
{ fF: "bar", fId: 1 },
{ fF: "buzz", fId: 2 }
];
return fFArray;
}
});
If you want state to be persisted across browser refreshes, you should be able to either fetch it from the server or from something like the Meteor Session.
The second thing you'd need is a helper to get the selected state. Conveniently, Meteor makes the data context available under this (for an each loop, this context is an individual item).
Template.userEdit.helpers({
userSelected: function() {
if(this.id === Session.get("selectedUserId")) {
return "selected";
}
}
});
This assumes you've set the Session variable previously with something like Session.set("selectedUserId", user._id).
Then in your template:
<template name="userEdit">
<select class="form-control" name="userSelect">
{{#each users}}
<option {{userSelected}}>{{username}}</option>
{{/each}}
</select>
</template>
(Note: The selected state can not actually be seen by inspecting the DOM with an element inspector.)
I'm not sure if this is the best answer to my problem, though this is what I came up with to add the selected attribute to the saved option. I welcome anyone else with a better/Meteor solution for this.
When the user clicks the edit link, I find the inputs that need to be updated and assign the values onClick. Ideally I'd rather have this already done on pageLoad, though feel that that solution may impact the initial pageLoad time.
Template.tItem.events({
'click .edit-t-item': function(e) {
e.preventDefault();
var $editTWrapper = $(e.currentTarget).next('.edit-t-wrapper');
$editTWrapper.find('[name=tNEdit]').val(this.tName);
$editTWrapper.find('[name=fFSelect]').val(this.fFId);
}
});

Categories

Resources