Vuetify combobox Value Set up - combobox

I used vuetify v-select but just change to v-combobox. There is a problem with value. For the v-select it was
[{
"text":"(NEC (1)) NEC work orders",
"value":"26729191407887178"
}]
After i changed to v-combobox it will show "26729191407887178". Is that possible to show (NEC (1)) NEC work orders in v-combobox?
<v-combobox
v-model="pwra.pwra_code"
label="Pwra Code"
:items="pwraCodeList"
dense
outlined
:hide-details="true"
:rules="[rules.required]"
></v-combobox>

You can set the return-object of <v-combobox/> to false then make a computed variable (in this example, its pwraCode) that finds the code in the pwraCodeList array and return it. If it isn't found, just return the typed input string.
<v-combobox
...
v-model="pwraCode"
:return-object="false"
>
</v-combobox>
// script
data: () => ({
pwra: {
pwra_code: "26729191407887178"
},
pwraCodeList: [...]
}),
computed: {
pwraCode: {
get: function() {
// find the code if it exist, else, just return the typed input
const code = this.pwraCodeList.find(
code => code.value === this.pwra.pwra_code
);
return code || this.pwra.pwra_code;
},
set: function(value) {
this.pwra.pwra_code = value;
}
}
}
Here's a demo at codesandbox:

What you need is to use the item-text prop. Just point it to the text key.
<v-combobox
v-model="pwra.pwra_code"
label="Pwra Code"
:items="pwraCodeList"
item-text="text"
dense
outlined
:hide-details="true"
:rules="[rules.required]"
></v-combobox>
And what dreamwalker said is true - it's just an extended v-select.

Related

React search and filter: TypeError: setFilterFn is not a function

I'm working on a search and filter function. When I type text into the search box, the content that matches the criteria will be filtered out. I want to use the following function to achieve this, but when I type, the "TypeError: setFilterFn is not a function" will occur.
I don't know where goes wrong, How should I fix it?
Thx a lot!
const [setFilterFn] = useState({ fn: items => { return items; } })
const handleSearch = e => {
let target = e.target;
setFilterFn({
fn: items => {
if (target.value != "")
return items;
else
return items.filter(item => item.fullName.toLowerCase().includes(target.value.toLowerCase()))
}
})
}
The quick fix... add a comma ...
const [,setFilterFn] = useState((items) => ( items));
it also looks as if you may have an issue with your logic..
if (target.value != "")
The operator here should probably be === otherwise you will only filter for blank strings.
Take a look at useState function, that function returning array with two arguments, first value of state , the second is callback function which will change your satate value. You are providing only one value, so react assuming that is value not a function. You can read more in docs

Modal popping up at the wrong time due to state

So I have two modals that I am using one of them was already implemented and behaves as expected however when I've added the other modal depending on the condition of if there is any true value when mapping over the array the way it works right now both modals show when there is a true value. I think this is because there are multiple false values returned from my .includes() function before the true appears. I think a good solution for this would be to make an array of all the values returned when I run .includes() on the entries then I can check that array for any true values but I cant seem to get the values into an array. When I try and push them into an array they just all push into their own separate arrays. This may be the wrong approach if it is can you explain what a better approach would be:
const checkPending = () => {
if(entries){
entries.map(descriptions => {
const desc = descriptions.description
//check if there are any pending tests
const check = desc.includes("pending")
//if the check returns true show the pending modal if it doesnt set the other modal to true
if(check === true){
setShowModal(false)
setShowPendingM(true)
}else{
setShowModal(true)
}
})
}
}
return(
<Button
onClick={() => checkPending()}
className={`${styles.headerButton} mr-2`}
>
Add File
<Plus />
</Button>
)
setShowModal & setShowPendingM are both passed from a parent component as props. They are both initialized as false. The most straightforward question I can pose is is there any way to say if there are any true values returned from .includes then do something even if there are false values present
I think this is how your checkingPending method should look like.
const checkPending = () => {
if(entries){
let pending = false;
entries.forEach((descriptions) => {
const desc = descriptions.description
if(desc.includes('pending')){
pending = true;
}
});
if(pending) {
setShowModal(false);
setShowPendingM(true);
} else {
setShowModal(true);
setShowPendingM(false);
}
}
}
Let me know if you have any additional questions.

TypeAhead with allowNew=false leaves input text when going out of focus

My users complain that they can enter new value (one that is not included in the options) even when that is not exactly the case.
When you input text, without selecting item from options and then leave the typeahead, the text stays there, which leads users to believe that new value (one that is not included in options) can be entered.
What would be the right way to deal with this?
I am quite new to frontend development, so the answer might actually be obvious.
One way to address this is to clear the typeahead when the user blurs the input unless they've made a valid selection. Here's an example:
https://codepen.io/anon/pen/qLBaYK
class BlurryTypeahead extends React.Component {
state = {
selected: [],
};
render() {
return (
<Typeahead
onBlur={this._handleBlur}
onChange={this._handleChange}
options={['one', 'two', 'three']}
ref={typeahead => this._typeahead = typeahead}
selected={this.state.selected}
/>
);
}
_handleBlur = () => {
// Check if there are selections.
if (!this.state.selected.length) {
// Clear the component if not.
this._typeahead.getInstance().clear();
}
}
_handleChange = (selected) => {
// Track the selected state
this.setState({ selected });
}
}

React-select unexpected async behavior

There is an unexpected behavior with the react-selectcomponent.
I have it set up to load external json to populate the list.
<Select.Async
name="cf_search"
value=""
autoload={false}
cache={false}
ignoreAccents={false}
loadOptions={this.handleCFSearch}
onChange={this.handleSelectCFName}
/>
handleCFSearch = (input) => {
let term = encodeURIComponent(input);
return fetch(`${AppGlobal.baseBackend}/PersAddo/autocompleteSearch/${term}.json`)
.then((response) => {
if(response.ok) {
return response.json();
}
throw new Error('Network response was not ok.');
}).then((json) => {
console.log(json);
let values = json.result.map((element) => {
return {
value: element.pers_id,
label: element.first_name + ' ' + element.last_name
}
});
return { options: values };
});
}
The server script handles the search term and returns an array with the names in JSON.
It works just fine but in some cases it doesn't work.
If I search 'morten twe' the result from the server shows up in the select.
However if I search 'morte twe' (just one character less in the first name) the list does not show up and the select box just looks like not results.
I have tested both search terms and they both return exactly the same JSON:
{
"result": [
{
"pers_id": 123456,
"first_name": "Morten",
"last_name": "Twellmann"
}
]
}
So why doesn't anything show up when the server returns the data correctly?
react-select does some client-side filtering by default. So even though your API is returning the value, react-select filters it out. The default filter implementation it uses can be found here . You can see the filterOptions prop being called here in Select.js, which Async utilizes.
The default filtering is basically just checking for substring, case-insensitive equality. In the case where the value is not shown, there is a difference between the search and the result, so it is filtered out.
You can provide your own filterOptions function to override the default, or just pass undefined to turn off the clientside filtering altogether.

AngularJS - Filter by any of the properties

I've got an application where I show a list of items with AngularJS. I'm trying to make an easy search on this list but it searches on everything inside that item. An example of an item:
{
id: 283727893,
name: 'Item A',
parent: {
id: 239495838,
name: 'Item B'
},
user: 'User C'
}
In the list I'm only writing the name of the root item, so parent.name does not appear.
The problem
However, if I search using an AngularJS filter by 'Item B', it still appears, because an inner property has this string.
What I've tried
I've put an object reference such as the following (where val is the text of the input):
vm.searchObj = {
name: val,
user: val
};
And then, on my DOM:
<li data-ng-repeat="[...] | filter: Ctrl.searchObj | orderBy: Ctrl.orderBy">
...
</li>
However, this works with conditional AND, so it only shows if both, name and user have val.
What I need
I'd like to take an input text and make a search to filter this list on given object properties (in plural).
So, in this example, this item should appear if I write 'Item A' or 'User C' (or just 'A' or just 'C' and so on), but not if I write 'B', because none of name and user have this letter.
I'd need it to take the reference object, in this case Ctrl.searchObj, and check if any of the given properties of the object contains val into the same structure of the filtered objects.
That, of course, should work into deeper levels of the object, so I could define the searchObj as follows and still be able to get if the filtered object has that structure inside:
vm.searchObj = {
parent: {
name: 'Item'
}
};
In this case, it should show those items where its parent.name property contains the word 'Item'.
If you need more information, please, let me know!
Thank you!
If I understand correctly, an object being searched (we'll call it target) is a match if:
both searchObj and target share at least one property name at the same level
The value of target's property is equal to or contains the value of searchObj's property
The code below (which includes your edits) should do what you need. I'll leave it to you to fill in any edge cases (checks for hasOwnProperty, comparison of different types, etc.). I think filtering like this should only happen when necessary, like when a user types. Creating an Angular filter out of this could be too expensive, since it runs on each digest cycle:
function objectContains(searchObj, target) {
for (var property in searchObj) {
var searchVal = searchObj[property];
var targetVal = target[property];
if (isObject(searchVal) && isObject(targetVal)) {
if(objectContains(searchVal, targetVal)){
return true;
}
}
if (
!isObject(searchVal) && !isObject(targetVal) &&
!isUndefinedOrNull(targetVal) &&
!isUndefinedOrNull(searchVal) &&
targetVal.toString().indexOf(searchVal.toString()) !== -1
) {
return true;
}
}
return false;
}
function isUndefinedOrNull(x) {
return typeof x === "undefined" || x === null;
}
function isObject(x) {
return typeof x === "object";
}
var filtered = list.filter(function(item) {
return objectContains(searchObj, item);
});
Try this way. Use true property on filter to get exactly what you search!
<li data-ng-repeat="[...] | filter: Ctrl.searchObj:true | orderBy: Ctrl.orderBy">
...
</li>
So, taking as the base the code by Frank Modica (thank you), I've come up with some editions on its compare function to look up not only for the first property, but if this does not match, keep up searching. This is the code modified:
function objectContains(searchObj, target) {
for (var property in searchObj) {
var searchVal = searchObj[property];
var targetVal = target[property];
if (isObject(searchVal) && isObject(targetVal)) {
if(objectContains(searchVal, targetVal)){
return true;
}
}
if (
!isObject(searchVal) && !isObject(targetVal) &&
!isUndefinedOrNull(targetVal) &&
!isUndefinedOrNull(searchVal) &&
targetVal.toString().indexOf(searchVal.toString()) !== -1
) {
return true;
}
}
return false;
}
In case it matches, it returns true because it needs only one match to be what we are looking for. In case it does not match, it keeps going.
We check for the second condition not to be an object neither of the values because they turn to [object OBJECT] when we apply toString(), so it returns true always. This way, if it's an object, it will ignore it (no need to do further checkings because we already done that in the first if).
Thank you Frank because I couldn't come up with this!
Now, it works perfectly!

Resources