Vue-multiselect: How to convert object to array for use in options prop? - javascript

I am using vue-multiselect like so:
<multiselect
id="customer_last_name_input"
v-model="value"
:options="activeUserProfiles"
label="lastname"
placeholder="Select or search for an existing customer"
track-by="uid"
:close-on-select="true"
#select="onSelect"
#remove="onRemove"
:loading="isLoading"
:custom-label="customerSelectName"
aria-describedby="searchHelpBlock"
selectLabel=""
>
...that grabs the list of active customers from an Array and then makes them available in a nice select menu.
This works good. However, I need to add another option from another resource (called customerNone) to the options prop and but the data is returned as an Object like so:
{"uid":1,"lastname":"None Given","firstname":"User","email":null,"phone":null...blah}
The vue-multiselect docs state that the :option prop MUST be an Array.
Question: What is the best way for me to handle this in the vue-multiselect component? Here's my attempt to help explain what I am trying to do (not sure if this is the best way to handle it). Unfortunately, my attempt causes a console error (see below):
I am passing a prop down called noCustomer which, if is true, I need to use customerNone profile on :options:
<multiselect
:options="noCustomer ? customerNone : getActiveUserProfiles"
>
here's the error:
Invalid prop: type check failed for prop "options". Expected Array, got Object
Is there a way I can convert the customerNone object to an array of object? Thanks!

You could wrap the customerNone object in brackets at the time that you pass it to the <multiselect> like [customerNone].
This syntax creates a new array on the fly, having 1 element that is the object variable:
<multiselect
:options="noCustomer ? [customerNone] : getActiveUserProfiles"
>
Update for comments
In order to auto-select the generic option when it's available, use a watch on the noCustomer prop to set value whenever noCustomer === true:
watch: {
noCustomer(newValue, oldValue) {
if(newValue) { // Checking that `noCustomer === true`
this.value = this.customerNone;
}
}
}

Related

Can I use a dynamic value to access a specific array in Vue.js?

I've been trying to figure out how to do this, but can't seem to get it to work. I have created a function that is being called when I click a component using v-on:click. I am also trying to pass in a value that I can then use to access a particular array that is coming in the form of data from a backend.
Here is the function in the component:
<v-card
#click="getContent('topSellers')"
>
I am then passing the 'topSellers' value as an "id" into the function that is being used to get access the exact array that I am looking for:
getContent(id) {
this.accordion = this.data.id;
console.log("data", id);
}
First of all, this.data.topSellers works. And I am seeing that the id value is correct in the console. Obviously, this is not working because id is currently a string, but I don't know how to fix that issue. Any help would be appreciated!
You need this.data[id] instead of this.data.id.
See property accessors on MDN for reference.
data[id] will access the property of data with the name of the value of id, in your case topSellers. So data.topSellers is equivalent to data["topSellers"]
[] allows you to access objects with variables.
It is recommended to handle exceptions because the variable received is not safe.
getContent(id) {
const accordion = this.data[id] || null;
if(accordion){
console.log("data", accordion);
this.accordion = accordion;
}
}

Conditional statement in V-Model

I have a dynamic form which contains a list of elements specified in the following way:
element1: { name: "property1", value: "value1", defaultValue: "defaultvalue1", usingDefaultValue: true, type: "String/Enum/Int/Long }
This list of elements is constantly published via a WebSocket and stored in a Vuex store. Each element corresponds to an input, which displays either the value or the defaultValue, depending on a toggle switch. These values are bound to the input fields using v-model.
I use the vuex-map-fields library to help with the dynamic multi row fields. They are defined as follows:
computed: {
...mapMultiRowFields(`elementsStore`, ["elements"])
},
The fields are passed into a list component using a v-for:
<v-layout v-for="element in elements" :key="element.name">
<element-list-item :element="element"></element-list-item>
</v-layout>
Now, the following works perfectly as I expect:
<v-text-field
v-model="element.useDefaultValue ? element.defaultValue : element.value"
</v-text-field>
However, whenever I use npm run lint, I get the following error message:
error: 'v-model' directives require the attribute value which is valid as LHS (vue/valid-v-model)
Is there a better way to achieve this same behaviour?
I'm going to assume the error message is there for a good reason.
One alternative approach I have tried is using a computed property. However, this did not work and immediately displayed errors in the console.

Angular ng-select : selectedItems.map is not a function

When I'm using ng-select in reactive form angular I get this error:
ERROR TypeError: selectedItems.map is not a function
I have 3 select the first two work very well but in this third one I get the error ! to map item i'm using the function (the ng-select is inside *ngFor) :
//for mappinig item :
mapLabelValueBS(objet) {
return objet.map(data => {
return {
id: data,
text: data.name
}
})
}
//this is the one that is causing the problem
<ng-select
[allowClear]="true"
[items]="mapLabelValueBS(filieres)"
placeholder="Filière non sélectionné"
(selected)="selecteFiliere($event)"
formControlName="filiere">
</ng-select>
the result in my page (when I click on the field it doubles itself) :
Without the code is difficult to know, but today I had the same error. The reason was that I determined a default value in the FormControl that had no relation with the array that ng-select demands. When the FormGroup loaded, and this mistaken default was loaded into the ng-select, the error was selectedItems.map is not a function
This error came while I was passing [items]="value" where the value was not an array, so please check if you are not passing non array element to items binding.
You are trying to bind the items of object type. [items] attribute accepts an array. You can trying adding a pipe keyvalue
<ng-select
[allowClear]="true"
[items]="jsonData | keyvalue"
placeholder="Filière non sélectionné"
(selected)="selecteFiliere($event)"
formControlName="filiere">
</ng-select>
few days ago i came across this error if you are binding a list that is filled from backend server be sure to fill the list using concat method like this
this.userService.getLookup().subscribe((res: any) => {
this.apps = this.apps.concat(res.data);
});
I had same problem, because the list of items was undefined sometime in the middle of page preparing, so I added a silly condition to show those select only when the list of items is ready:
<ng-select
*ngIf="selectedItems.map"
[allowClear]="true"
[items]="jsonData | keyvalue"
placeholder="Filière non sélectionné"
(selected)="selecteFiliere($event)"
formControlName="filiere">
</ng-select>

How can I create data-driven text inputs with Ember?

I am trying to create several inputs that update my Ember Data model immediately, without a submit action. E.g.
Person
First Name [Placeholder: Enter first name ]
Last Name [Placeholder: Enter last name ]
City [Placeholder: Enter city ]
I’ve approached this by creating a wrapper component around an Ember TextField subclass component, and have gotten it to work, kind of, but with two major problems:
Placeholders don't work as I tried to implement them (see below) — seems I could do this a lot more easily using the TextSupport mixin, but I don't know how to use it.
I don't like the way I am sending change actions up to the route, which is basically like this:
Within a top-level component {{person-view action="modifyPersonInternals"}} I have my wrapper components as follows:
{{editable-property property="firstName" action="updateFirstName"}}
{{editable-property property="lastName" action="updateLastName"}}
{{editable-property property="city" action="updateCity"}}
When the user edits the firstName, the TextField component calls updateFirstName on the editable-property wrapper component with a parameter (the new value); the wrapper component in turn calls modifyPersonInternals on the route with two parameters (the property to modify, and the new value). This works but seems clunky/hacky and can't be the right approach, can it?
Also, here's my unsuccessful attempt to implement a placeholder in editable-property.js,
hasEmptyProperty: Ember.computed(function() {
return ((this.get('property') === "") || (this.get('property') === null));
})
and in editable-property.hbs:
{{#if hasEmptyProperty}}
<div class="placeholder" {{action "editProperty"}}>{{placeholder}}</div>
{{else}}
<div {{action "editProperty"}}>{{bufferedProperty}}</div>
{{/if}}
I get an error that hasEmptyProperty is not defined.
If you are passing the model into the component anyway, why not just directly associate the models property with your input?
{{input value=model.firstName}}
This will achieve your goal, but if you are trying not to pass the model into the component then the best way is to send an action as you are doing.
With regard to the hasEmptyProperty I would instead have a property called hasEmptyProperty and a function that sets it, something like...
checkEmptyProperty: function() {
var property = this.get('property');
if(property === "" || property === null ) {
this.set('hasEmptyProperty', true);
} else {
this.set('hasEmptyProperty', false);
}.observes('property'),

How to interact with a Component's aggregation

I've configured an aggregation for my Component. It looks like this:
aggregations : {
busyDialog : {
type: "sap.m.BusyDialog",
multiple: false
}
}
So, the aggregation is called "busyDialog" and can contain objects of the type "sap.m.BusyDialog".
I'm also able to get the object with its settings via my.ui5.namespace.Component.getMetadata().getAggregations().busyDialog
However, I'm not sure what's the best way to add an item to it or access an already added control in the aggregation. Are there any methods like "addbusyDialog" or something?
Was following this:
http://help.sap.com/saphelp_hanaplatform/helpdata/en/01/87ea5e2eff4166b0453b9dcc8fc64f/content.htm?fullscreen=true
OpenUI5 automatically generates the following methods for aggregations where multiple is false (where item is the name of the aggregation):
setItem(oItem)
getItem()
destroyItem()
And it creates these methods where multiple is true:
addItem(oItem)
insertItem(oItem, iIndex)
getItems()
indexOfItem(oItem)
removeItem(vItem) // item or index of item
removeAllItems()
destroyItems()
To answer your specific question, the best way to manipulate your busyDialog aggregation is to use these generated methods:
myComponent.setBusyDialog(oBusyDialog);
myComponent.getBusyDialog();
myComponent.destroyBusyDialog();
Source: https://openui5.hana.ondemand.com/docs/api/symbols/sap.ui.base.ManagedObject.html

Categories

Resources