I am learning Vue.js and I am setting up a website where I am using LocalStorage to store data.
I wrote some code, which is a little clunky and very repetitive:
<script>
const app = new Vue({
el:'#app',
data:{
explosive_pullups_1: '',
explosive_pullups_2: '',
explosive_pullups_3: '',
tuck_front_raises_1: '',
tuck_front_raises_2: '',
tuck_front_raises_3: '',
},
mounted() {
if (localStorage.explosive_pullups_1) {
this.explosive_pullups_1 = localStorage.explosive_pullups_1;
}
if (localStorage.explosive_pullups_2) {
this.explosive_pullups_2 = localStorage.explosive_pullups_2;
}
if (localStorage.explosive_pullups_3) {
this.explosive_pullups_3 = localStorage.explosive_pullups_3;
}
if (localStorage.tuck_front_raises_1) {
this.tuck_front_raises_1 = localStorage.tuck_front_raises_1;
}
if (localStorage.tuck_front_raises_2) {
this.tuck_front_raises_2 = localStorage.tuck_front_raises_2;
}
if (localStorage.tuck_front_raises_3) {
this.tuck_front_raises_3 = localStorage.tuck_front_raises_3;
}
},
watch: {
explosive_pullups_1(pullups1) {
localStorage.explosive_pullups_1 = pullups1;
},
explosive_pullups_2(pullups2) {
localStorage.explosive_pullups_2 = pullups2;
},
explosive_pullups_3(pullups3) {
localStorage.explosive_pullups_3 = pullups3;
},
tuck_front_raises_1(tuck_front_raises1) {
localStorage.tuck_front_raises_1 = tuck_front_raises1;
},
tuck_front_raises_2(tuck_front_raises2) {
localStorage.tuck_front_raises_2 = tuck_front_raises2;
},
tuck_front_raises_3(tuck_front_raises3) {
localStorage.tuck_front_raises_3 = tuck_front_raises3;
},
}
})
</script>
I would like to know a way to write this code to be less repetitive.
You can put the exercise data into its own object, and save that to localStorage instead. E.g.:
<script>
const app = new Vue({
el:'#app',
data: {
exercises: {},
},
mounted() {
this.exercises = JSON.parse(localStorage.getItem("exercises"));
},
watch: {
exercises(newExerciseValues) {
localStorage.setItem("exercises", JSON.stringify(newExerciseValues));
},
}
})
</script>
If you really need to store and retrieve the individual exercises explicitly, I would recommend keeping the data in one exercises object, and simply use a for loop to check/set everything. Something like this:
[...]
watch: {
exercises(newExercises) {
const exercisesToCheck = [
'explosive_pullups_1',
'explosive_pullups_2',
'explosive_pullups_3',
'tuck_front_raises_1',
'tuck_front_raises_2',
'tuck_front_raises_3',
];
for (const exercise of exercisesToCheck) {
localStorage.setItem(exercise, this.exercises[exercise]);
}
},
},
[...]
On a side note, be very careful when working with objects in Vue. If you need to add a new exercise to the exercises object, avoid using this.exercises['new_exercise'] = newExercise. Instead, use Vue.set(this.exercises, 'new_exercise', newExercise). Check out the Vue docs for an explanation.
Related
I have created a plugin in the adminstration and I want to insert the manyToMany products with vehicles into Shopware 6 database. From the code below I am trying to insert '92961afbc50e4380b3af86b257630ade' into the 'product_id' column of the 'vehicles_product' table :
import template from './sw-vehicles-import.html.twig';
const { Component, Mixin } = Shopware;
Component.register('sw-vehicles-import', {
template,
inject: ['importExport', 'repositoryFactory', 'feature'],
mixins: [
Mixin.getByName('notification'),
],
metaInfo() {
return {
title: this.$createTitle()
};
},
data() {
return {
importFile: null,
repository: null,
entity: undefined,
};
},
computed: {
},
created() {
this.repository = this.repositoryFactory.create('vehicles');
},
methods: {
onStartProcess() {
this.entity = this.repository.create(Shopware.Context.api);
this.entity.categoryFilter = 'CategoryName';
this.entity.featureFilter = 'FeatureName';
this.entity.products.productId = '92961afbc50e4380b3af86b257630ade';
this.repository.save(this.entity, Shopware.Context.api);
}
}
});
The build process doesn't work, what am I doing wrong? Could you help me please ?
You need to create a new entity collection for the association if it doesn't exist yet.
const { EntityCollection } = Shopware.Data;
if (!this.entity.products) {
this.entity.products = new EntityCollection(
'/product',
'product',
Shopware.Context.api
);
}
const product = await this.repositoryFactory.create('product').get('92961afbc50e4380b3af86b257630ade', Shopware.Context.api);
this.entity.products.add(product);
this.repository.save(this.entity, Shopware.Context.api);
I've had a problem
data() {
return {
list: [],
initState: { id: null, data: null }
}
},
computed: {
...mapState({
contacts: (state) => state.ContactBook.Contacts
})
},},
methods: {
setinitState(payload) {
this.initState.data = contacts[this.contactID]
},
How Can I make this.initState static? I need this.initState didnt changes when contacts[this.contactID] changes...
You may use the spread operator like this,
this.initState.data = {...contacts[this.contanctID]}
Spread Operator MDN
state.snapshot = JSON.parse(JSON.stringify(state.Contacts[payload]))
I'm having problems defining the initialValue in an Upload component, other thing I tried was using a watcher and updating the formValue and the method that update the props FileList. ¿Someone has any idea how this work?
Parent.vue
<Child :file="file"/>
...
async loadFile(item) {
this.loading = true
const { data } = await axios(..., {
...
responseType: 'blob',
})
const file = new File([data], item.name, { type: data.type });
this.file= {
Id: item.id,
Type: item.attributes.type,
IsPublic: item.attributes.is_public,
Descr: item.attributes.descr,
File: [file]
}
this.showForm();
this.loading = false
},
Children.vue
<a-upload
:accept="formats"
:before-upload="beforeUploadEvt"
:disabled="!formats"
:remove="removeFileEvt"
v-decorator="[
'File',
{
valuePropName: 'fileList',
getValueFromEvent: getValueEvt,
rules: [{ required: true, message: 'Select a file' }]
},
]" >
<a-button> <a-icon type="upload" /> Select a file</a-button>
</a-upload>
methods: {
beforeUploadEvt(file) {
this.form.setFieldsValue({
File: [file]
});
return false;
},
removeFileEvt() {
this.formulario.setFieldsValue({
Archivo: []
});
},
getValueEvt(e) {
if (Array.isArray(e)) {
return e;
}
if(e && e.fileList.length > 1) {
return e && [e.fileList[1]];
}
return e && e.fileList;
},
},
watch: {
adjunto: {
immediate: true,
deep: true,
handler(obj) {
if(obj.File) {
this.getValueEvt(obj.File);
// this.formulario.setFieldsValue({
// File: obj.File
// });
}
}
}
}
Trying the most basic example I could think, using the property defaultFileList
<a-upload
:accept="formats"
:before-upload="beforeUploadEvt"
:disabled="!format"
:remove="removeFileEvt"
:default-file-list="this.file.File">
<a-button> <a-icon type="upload" /> Select file</a-button>
</a-upload>
And then, this is the console warnings and errors I got, so seems to be something about type.
If anyone still seeking for an answer for this. You don't need to load file, wrapping your data in appropriate object helps. As in this example
fileList: [{
uid: '-1',
name: 'image.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
}]
<a-upload
....
:file-list="fileList"
>
In all the ag-grid-vue examples, data of rows are generated in the component's method of createRowData(), which is simple but not realistic.
I want to see an example in which row-data are provided to ag-grid vue component from the parent Vue instance.
If there's such information, please let me know.
I found a way by using Veux. Here's an example.
Appication.
let gridRows = {
state: {
rowData: []
},
mutations: {
push(state, rows) {
while( 0 < rows.length ){
state.rowData.unshift(rows.pop());
}
},
getters: {
rowData: state => {
let rows = state.rowData;
return state.rowData;
}
}
};
let store = new Vuex.Store(gridRows);
let app01 = new Vue({
el: '#app',
store,
render: h => h(DynamicComponentExample)
});
let rowData = [];
for (var i=0; i < 15; i++) {
rowData.unshift({
row: "Row " + i,
value: i,
currency: i + Number(Math.random().toFixed(2))
});
}
store.commit('push', rowData);
Component (modification to DynamicComponentExample.vue)
data () {
return {
gridOptions: null,
columnDefs: null
//rowData: null
}
},
computed: {
rowData(){
return this.$store.getters['rowData'];
}
},
beforeMount() {
...
//this.createRowData();
this.initColumnDefs();
},
I'm using vue-js 2.3 and element-ui. This question is more specific to the MessageBox component for which you can find the documentation here
Problem
I'd like to be able to enter html message in the MessageBox
More specifically I would like to display the data contained in dataForMessage by using a v-for loop.
Apparently, we can insert vnode in the message but I have no idea where to find some information about the syntax.
https://jsfiddle.net/7ugahcfz/
var Main = {
data:function () {
return {
dataForMessage: [
{
name:'Paul',
gender:'Male',
},
{
name:'Anna',
gender:'Female',
},
],
}
},
methods: {
open() {
const h = this.$createElement;
this.$msgbox({
title: 'Message',
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode '),
h('span', null, 'but I would like to see the data from '),
h('i', { style: 'color: teal' }, 'dataForMessage'),
])
}).then(action => {
});
},
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
I think this is what you want.
methods: {
open() {
const h = this.$createElement;
let people = this.dataForMessage.map(p => h('li', `${p.name} ${p.gender}`))
const message = h('div', null, [
h('h1', "Model wished"),
h('div', "The data contained in dataForMessage are:"),
h('ul', people)
])
this.$msgbox({
title: 'Message',
message
}).then(action => {
});
},
}
Example.
You can also use html directly and convert to vnodes by using domProps:
const html = '<div><h1>Model wished</h1><div>The data contained in dataForMessage are:</div><ul><li>Paul Male</li><li>Anna Female</li></ul></div>'
const message = h("div", {domProps:{innerHTML: html}})
(The above is simplified without the loop. Just to get the idea)
Fiddle