Vue.js: Give a nested property/attribute a custom value - javascript

In my view (HTML) I want to show this:
<p>Age: {{ user.age }} years</p>
In my javascript this is what I have:
new Vue({
el: '#userApp',
data: {
user : user,
alergies : user.alergies,
conditions : user.conditions,
drugs : user.drugs,
solicitudes: solicitudes,
},
computed: {
},
filters: {
active: function(elements) {
return elements.filter(function(element){
return ! element.fecha_fin;
});
}
},
methods: {
}
});
How do I modify the age in the computed properties? I tried doing this
computed: {
user.age: 10
},
but it won't allow it.
Note: I'm getting user, solicitudes from the server.

Computed properties are functions that you use as properties.
In your case, I think that you can use age like you're doing with the drugs or conditions. Than the 2 way data bindings take care of that.
data: {
user : user,
alergies : user.alergies,
conditions : user.conditions,
drugs : user.drugs,
age : user.age,
solicitudes: solicitudes,
}
Based on your comment bellow, maybe you can use this:
compiled: {
user[age] = theAgeOfTheUser
}
That method will create a new property on the user object. Then you can modify like any other value.

Related

Understanding the order of properties execution in Vuejs [duplicate]

This question already has answers here:
Access vue instance/data inside filter method
(3 answers)
Closed 2 years ago.
I'm creating a simple Vuejs div component (to show a specific value) which needs to receive: a lists, a placeholder and a value as props. What I'm trying to do is displaying the value with the data from my database, if the user picks a new value from the lists, it should take that new value and display it. However, if the user never picks a new value and the data from the database is empty, it should display the placeholder.
So I have used filters to achieve this. However, it outputs an error: "Cannot read property 'lists' of undefined", which comes from the filters (I know because it outputs no error if I comment out the filters). When I changed the filter to this:
filters: {
placeholderFilter () {
return this.placeholderText || this.placeholder
}
}
It says:""Cannot read property 'placeholderText' of undefined"". So I was wondering if the filters properties executed before the data and props properties. What is the execution order of them? I have attached some of the relevant code down below. Anyway, If you could come up with a better way to achieve this. I would appreciate it!
Here is my component:
<template>
<div>{{ placeholderText | placeholderFilter }}</div>
<li #click="pickItem(index)" v-for="(list,index) in lists" :key="index">{{ list }}</li>
</template>
<script>
export default {
props: {
lists: {
type: Array,
required: true
},
value: {
type: [String, Number],
default: ''
},
placeholder: {
type: String,
default: ''
}
},
data () {
return {
selected: -1,
placeholderText: this.value || this.placeholder
}
},
methods: {
pickItem (index) {
this.selected = index
}
},
filters: {
placeholderFilter () {
return this.lists[this.selected] || this.placeholderText || this.placeholder
}
}
}
</script>
And this is where I use it:
<my-component
placeholder="Please type something"
value="Data from database"
lists="['option1','option2','option3']"
>
</my-component>
Filters aren't bound to the component instance, so they simply don't have access to it through the this keyword. They are meant to always be passed a parameter and to return a transformed version of that parameter. So in other words, they're just methods. They were removed in Vue 3 entirely probably for that reason.
And yeah, what you're looking for here is a computed!

How to handle Laravel to Vue.js boolean values

I've got an input field that looks like the following :
<tr v-for="(item, index) in collection">
...
<input
type="checkbox"
v-model="item.activated"
#change="toggleSwitch(item.resource_url, 'activated', item)">
>
...
</tr>
The collection is an array containing several keys, activated is one of them. activated is equal to 1 or 0 as the data is coming from a mysql database. The problem is that the input field is always set to true in this case, even if the activated is equal to 1 or 0.
Now, I tried writing the v-model like so to fix the issue :
v-model="!!+item.activated"
as by adding !!+ I'd convert the integer value to a boolean and use that. That fixes the issue, but creates another. The other issue I get by doing so is when I try to change my checked input I get an error :
[Vue warn]: Cannot set reactive property on undefined, null, or primitive value: false
admin.js:120238 TypeError: Cannot use 'in' operator to search for 'activated' in false
The toggleSwitch method looks like this :
toggleSwitch: function toggleSwitch(url, col, row) {
var _this8 = this;
axios.post(url, row).then(function (response) {
_this8.$notify({ type: 'success' });
}, function (error) {
row[col] = !row[col];
_this8.$notify({ type: 'error' });
});
},
I'm new to Vue.js, any idea how to debug this and where could my problem be coming from? I'll gladly give any additional info.
Edit :
Here's my component
Vue.component('profile-edit-profile-form', {
mixins: [AppForm],
data: function() {
return {
form: {
...
activated: false ,
...
}
}
}
});
If you use AJAX to populate your collection, then you should convert your 0 and 1 strings to booleans in your AJAX callback before injecting them into your component. Or even better you could convert them directly from your controller, by the way you directly get true|false
data.forEach(function(entry) {
if(entry.hasOwnProperty("activated"))
entry.activated = !!+entry.activated
});
my recommendation is:
Database column "activated" tinyint(1)
in laravel model use $cast array to cast "activated" to "boolean"
in vue use native type boolean for form.activated with true and false
Laravel Model:
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'minimum' => 'float',
'maximum' => 'float',
'step' => 'float',
'minItems' => 'integer',
'maxItems' => 'integer',
'uniqueItems' => 'boolean',
];
Vue:
<b-form-radio-group id="uniqueItems" v-model="formData.uniqueItems" :options="optionsBoolean" name="uniqueItems" :/>
optionsBoolean (){
return [
{ text: 'Yes'), value: true },
{ text: 'No'), value: false }
]
}

VueJs insert into nested list

I want to let the user create the structure of my website. For example, I have buildings and rooms. The user must be able to create a building and subsequently insert rooms into it. However, what I tried to do seems not to achieve it:
JSFiddle of what I have done so far.
js
new Vue({
el: '#vue-app',
data: {
buildings: []
},
computed: {
buildingCount() {
return this.buildings.length
},
getBuildingRoomsLength(section) {
return this.buildings.rooms.length
}
},
methods: {
addNewRoomToBuilding(buildingId, newRoom) {
if(newRoom !== undefined) { this.buildings[parseInt(buildingId)-1].rooms.push(newRoom.title)
console.log(this.buildings[parseInt(buildingId)-1])
}
},
addNewBuilding() {
this.buildings.push({
id: this.buildings.length+1,
rooms: []
})
},
deleteTodo(todo) {
this.todos.$remove(todo)
}
}
});
I am not sure how to make it work. A couple of the things I have noticed is that the room model now is same for all buildings and I have to change it according to the buildingId, however, I can't figure it out yet. Could you please assist me how to do this.
Make your model unique for each item in the buildings array by appending the building id to the end of the name.
So the model name becomes v-model="newRoom[building.id]"
And pass the same into your method addNewRoomToBuilding(building.id, newRoom[building.id])

Upsert data with a dynamic field name

I just try to do something simple with Mongo but it doesn't work:
I want to upsert datas in an object like: module.xxx.yyy then I tried many things like :
UsersRights.upsert({
condoId: condoId,
userId: manager._id,
}, {
condoId: condoId,
userId: manager._id,
module: {
[defaultRight.xxx] : {
[defaultRight.yyy] : defaultRight.default
}
}
});
but when I want to add a new xxx or a new yyy, it will erase and replace the entire module object and not only add a new key.
I also tried this :
UsersRights.upsert({
condoId: condoId,
userId: manager._id,
}, {
condoId: condoId,
userId: manager._id,
["module." + defaultRight.module + "." + defaultRight.right] : defaultRight.default,
});
but the server show me an error like: MinimongoError: Key module.xxx.yyy must not contain '.'
You need to use the following form:
YourCollection.upsert({
_id: id, (can be other selectors as well)
}, {
$set: setter
});
Setter is an object you create before and should have the following form:
const setter = {};
setter[`${#1Level}.${#2Level}`] = data;
Where #1Level & #2Level are vars naming the fields you want to modify or to add.

how to write validation in sencha touch / ext js model

I have a model like this
Ext.define('app.model.TeamEmpAssignment', {
extend : 'Ext.data.Model',
config : {
idProperty : 'teamEmpId',
fields : [{
name : 'teamEmpId',
type : 'int'
}, {
name : 'actName'
}, {
name : 'beginDateTime'
}, {
name : 'endDateTime'
},
],
validations : [{
field : 'beginDateTime',
type : 'presence',
message : 'Effective Begin Date Time required'
}, {
field : 'endDateTime',
type : 'presence',
message : 'Effective End Date Time required'
},
],
}
});
I have to write a validation to compare that endDateTime > startDateTime
I am trying sencha touch 2.3.1
I know this is an old question, but I ran into it while dealing with the same problem and wanted to share my approach.
I created a method in the model, which does the custom validation, something like:
Ext.define('app.model.TeamEmpAssignment', {
extend : 'Ext.data.Model',
config : {
// config here
},
checkDates: function (errors) {
// assuming the dates are timestamps
if (this.get('beginDateTime') > this.get('endDateTime')) {
errors.add(Ext.create('Ext.data.Error', {
field : 'beginDateTime',
message: 'Begin date can\'t be after end date'
}));
}
}
});
You will notice that checkDates has one argument - errors. This argument is actually the Ext.data.Errors object return by the validate method of the model. So we can do something like:
var record = Ext.create('Ext.data.Errors');
// set some values here
var errors = record.validate();
record.checkDates(errors);
console.log(errors.isValid());
We can use isValid, because all it does is check whether the Ext.data.Errors collection has items.
I am currently using it like this, however it will be quite easy to override the validate method, so you don't have to call the custom validation externaly.
Ext.define('app.model.TeamEmpAssignment', {
extend : 'Ext.data.Model',
config : {
// config here
},
checkDates: function (errors) {
// assuming the dates are timestamps
if (this.get('beginDateTime') > this.get('endDateTime')) {
errors.add(Ext.create('Ext.data.Error', {
field : 'beginDateTime',
message: 'Begin date can\'t be after end date'
}));
}
},
validate: function () {
var errors = this.callParent(arguments);
this.checkDates(errors);
return errors;
}
});
The validation types come from the Ext.data.validations singleton. You can add your own validators here, however the method does not supply the all the fields in the model (which it sounds like you will need). We would advise moving your validators to a different spot (outside the model), maybe on the related form component (after a load or before a save).

Categories