I have a component that builds exercices and series for a workout.
In the Workout vue I call the component and pass multiple props to build the workout as I want.
For exemple :
<WorkoutComponent
Exercices=[
{exName: 'Exercice 1',
exDescription: 'The description...',
nbSeries: 6},
{exName: 'Exercice 2',
exDescription: 'Another description...',
nbSeries: 3}]/>
It works fine but when I want to build antoher workout using the same exercices I have to enter the description again (and other fields that I don't show here).
I want to use just the name of the exercice. The other fields would be called from elsewhere (another prop ? a file ?).
It would look like this (some fields would be completed automatically, such as the description):
<WorkoutComponent
Exercices=[Exercice 1,
nbSeries: 6},
{exName: 'Exercice 2',
nbSeries: 3}]/>
I tried to insert a prop in the prop like so:
<WorkoutComponent
Exercices=[{{exList.Exercice1}},
nbSeries: 6},
{exName: {{exList.Exercice2}},
nbSeries: 3}]/>
Tried with exList imported as a .json or a .js but it didn't work.
What could I do ?
Anything you bind to a prop should be a valid JavaScript expression.
This is not a valid JavaScript expression:
[{{exList.Exercice1}},
nbSeries: 6},
{exName: {{exList.Exercice2}},
nbSeries: 3}]
I think you mixed up Vue's text interpolation binding syntax with props binding.
So, your prop binding should look like this:
<WorkoutComponent
:Exercices="[
{
exName: exList.Exercice1,
nbSeries: 6
},
{
exName: exList.Exercice2,
nbSeries: 3
}
]"
/>
On a side note, you should maintain the Exercises prop value in a computed() or ref() to avoid cluttering template.
Solved.
I have my exercices list in a ts file :
const exercices = [
{
"exercice":'DIPS',
"image":'DIPS.png',
"muscles":'...',
"instructions":'...'
},
{
"exercice":'PUSHUPS',
"image":'PUSHUPS.png',
"muscles":'...',
"instructions":'...'
}]
export default exercices
In my vue I import the file and assign exercices to const :
import exercices from '#/components/ExercicesList';
const DIPS = exercices.find(DIPS => DIPS.exercice === 'DIPS');
const PUSHUPS = exercices.find(PUSHUPS => PUSHUPS.exercice === 'PUSHUPS');
Then I use it in my props like this :
<WorkoutComponent workout="Workout 1" :exercices="[
{
exercice: DIPS?.exercice,
series:6,
image: DIPS?.image,
muscles: DIPS?.muscles,
instructions: DIPS?.instructions,
timer_duration: 25
},
{
exercice:PUSHUPS?.exercice,
series:3,
image:PUSHUPS?.image,
muscles:PUSHUPS?.muscles,
instructions:PUSHUPS?.instructions,
timer_duration: 25
}]
It works now :)
Related
I'm trying to make a graph with libraries on nuxt
I'm looking to use chartist but it doesn't work for now.
Link chartist: https://gionkunz.github.io/chartist-js/getting-started.html
I'm trying diplay the diagram by following the get started part.
In my component, i'm doing this:
<template>
<canvas class="ct-chart ct-perfect-fourth" />
</template>
export default {
created() {
this.creatChart();
},
methods: {
creatChart() {
const data = {
// A labels array that can contain any sort of values
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
// Our series array that contains series objects or in this case series data arrays
series: [
[5, 2, 4, 2, 0]
]
}
const chart = new Chartist.Line('.ct-chart', data);
return chart;
},
},
}
And i receive this error : Cannot read property 'querySelectorAll' of null
Of course chartist is installed with npm...
Instead of created() {} to init your Chartist, you must use the mounted() {} method to init your chart only on client side.
mounted() {
this.creatChart();
},
The "created" hook will be run twice once on server-side, then once on client-side. The "mounted" will be run only once on client-side.
Chartist is only available on client-side (browser), due to the usage of document.querySelectorAll.
But on server-side (Node.js), document does not exist... which explains your error of Cannot read property 'querySelectorAll' of null.
I've been trying to pass a prop in a component's template.
I think I'm missing some points here, and I didn't start to include my components in single files yet.
app.js
Vue.component('chat-response', {
props: ['response', 'senderClass'],
template: '<div>From {{ senderClass }} : {{ response.text }}</div>'
})
var app = new Vue({
el: '#app_chat',
data: {
responseList: [
{ id: 0, text: 'Response 1', type: 'Owner' },
{ id: 1, text: 'Response 2', type: 'Other' },
{ id: 2, text: 'Response 3', type: 'None' }
]
}
})
page.html
...
<chat-response v-for="response in responseList"
v-bind:key="response.id"
v-bind:response="response"
v-bind:senderClass="response.type"></chat-response>
...
Output :
From : Response 1
From : Response 2
From : Response 3
As we see, senderClass won't show up. I've tried different methods and only got errors that I could understand after reading around.
I don't wish to use response.type instead of senderClass because in the meantime, I'm setting senderClass after mounted with a real css class.
Maybe it's my approach that's completely wrong, could you give me some hints ?
I think the name of your property is wrong. Just change in page.html v-bind:senderClass="response.type" to v-bind:sender-class="response.type"
http://jsfiddle.net/eywraw8t/310360/
HTML attribute names are case-insensitive. Any uppercase character will be interpreted as lowercase. So camelCased prop names need to use their kebab-cased equivalents.
Apart from what Jns said You could get rid of v-bind altogether and just use :varibaleName for bindings.
Link to fiddle
https://jsfiddle.net/50wL7mdz/654614/#&togetherjs=J9vgbNaR7m
I'm trying to make a suffix change in an email input when I change an option.
Here is different parts of my code:
<q-field
icon="work"
label="Institution"
:label-width="3"
>
<q-option-group
type="radio"
v-model="institution"
#change="changeInstitution"
:options="[
{label: 'Institution 1', value: 'I1', suffix: '#institution1.fr'},
{label: 'Institution 2', value: 'I2', suffix: '#institution2.fr'}
]"
/>
</q-field>
<q-field
icon="email"
label="Adresse courriel"
:label-width="3"
>
<q-input v-model="email" type="email" suffix="" />
</q-field>
I also have these lines:
<script>
export default {
methods: {
changeInstitution () {
console.log('Change institution')
}
},
data () {
return {
institution: '',
email: ''
}
}
}
</script>
The problem is that when I change the "Institution" choice, I don't have the expected log ("Change institution"). Instead, I have this:
[Vue warn]: Missing required prop: "value"
found in
---> <QInput>
<QField>
<QTabPane>
<QTabs>
<QModal>
<QDialog>
<Testlogin> at src/components/views/testlogin.vue
<QToolbar>
<QLayoutHeader>
<QLayout>
<LayoutDefault> at src/layouts/default.vue
<Root>
Can anyone give me a hint? I looked at the documentation (http://quasar-framework.org/components/option-group.html#Installation), up to no avail...
Thanks in advance.
You're using v-model. This is equivalent to
:value="model" #input="(newVal) => model = newVal"
So, as a result, #change does not gets called, since #input is emitted first, changes the model, then Quasar components get to compare the emitting value to the model... but since v-model's #input changed model, now the emitting value is same, so Quasar components skip the #change event.
Either use:
v-model along with #input
The "lazy" equivalent of v-model (:value="model" #change="(newVal) => { model = newVal; callSomething...() }")
I need to statically pass an array to my Vue component, called ajax-table. I can't seem to find a way to do it, so I came up with this:
<ajax-table
header-names="Code, Name, Description, Type"
field-names="code, name, description, major_type">
</ajax-table>
Inside the component, I do this:
export default {
props: [
'headerNames',
'fieldNames'
],
data: function () {
return {
columnHeaders: [],
columnFields: []
}
},
created() {
this.columnHeaders = this.headerNames.split(",").map(x => x.trim());
this.columnFields = this.fieldNames.split(",").map(x => x.trim());
}
}
Now, columnHeaders and columnFields contain the header-names and field-names that I passed statically to the component.
My question:
Is there a better way to do this?
You should be able to directly pass the array to props using v-bind: directive or : for short:
<ajax-table
:header-names="['Code', 'Name', 'Description', 'Type']"
:field-names="['code', 'name', 'description', 'major_type']">
</ajax-table>
Now props headerNames and fieldNames are arrays, which you can use in the component.
I'm working with react-select, to add a multi-select control in my web-app. http://jedwatson.github.io/react-select/
I'm looking for a good example to inject mobx observables into the control.
The first challenge I have is initialising the options in an async way (options are fetched from server, but after that I want regular filtering to apply, no need for async-options).
Any good examples out there?
import Select from 'react-select';
<Select
multi
disabled={this.state.disabled}
value={this.state.value}
placeholder="Select your favourite(s)"
options={this.state.options}
onChange={this.handleSelectChange}
/>
As noted in MobX documentation, due to limitations in ES5, ObservableArray still has some quirks. react-select is one of those libraries that don't work with ObservableArray out of the box. There are 2 ways to solve this.
Method 1
you already have an observable array with label and value
#observable myOptions = [
{label: 'foo', value: 123},
{label: 'bar', value: 345}
]
then you can use the ObservableArray's .peek() method to return a regular array for read-only purposes
<Select
options={this.myOptions.peek()}
onChange={this.handleSelectChange}
/>
Method 2
You have the observable array in some other format, returned from server. This is a more common case, actually.
#observable peopleData = [
{name: 'foo', _id: 123, address: 'fooville'},
{name: 'bar', _id: 345, address: 'barville'}
]
in this case, you can create a #computed value, which also returns a plain array:
#computed get peopleOptions() {
return this.peopleData.map(x => ({ label: x.name, value: x._id })
}
and connect the Select component to the computed value, which will auto-update each time new data from server are fetched.
<Select
options={this.peopleOptions}
onChange={this.handleSelectChange}
/>
in both cases, this.handleSelectChange should just update the original data.