I've created a dynamic Custom Component and i wanna register/add a custom event on this component,like:
<SelectContactRowComponent #customevent="custommethod()"></SelectContactRowComponent
This is my dynamic customcomponent code:
var RowComponent = Vue.extend(SelectContactRowComponent);
var instance = new RowComponent( {propsData: {
item_data: {'lastname': '', 'firstname' : '', 'email' : '', 'telephone' : ''},
isDOMadd : true,
data_source_url : this.data_source_url,
id: this.id,
id_name: this.id_name,
morph_class_id: this.morph_class,
}
}).$mount();
You should do that in your emit option of the SelectContactRowComponent
const app = Vue.createApp({})
app.component('select-contact-row-component', {
emits: ['customevent']
})
Then you can emit it within the SelectContactRowComponent methods, or lifecycle hooks depending on your logic
this.$emit('customevent', { payload })
Related
I need to create an instance and then return it as $el. nodeTemplate is a function in mounted hook. But i have an error that in VisualComponent $store is not defined on the instance but referenced during render.
import router from "../../router";
import store from "../../store";
...
const nodeTemplate = (n, parent, cyn) => {
// parent is the same as window
const Card = Vue.use(store).use(router).extend(Visual);
const instance = new Card({
propsData: {
vis: n.graphData ? n.graphData : {},
visualType: n.visualType ? n.visualType : {},
size: '',
className: cyn.classes(),
},
});
instance.$mount();
return instance.$el;
};
...
cy1.nodeHtmlLabel([
{
query: 'node',
tpl: function (n) {
n.el = nodeTemplate(n, parent, cy1.$(`#${n.id}`));
return n.el
}
}
])
I have the following data structure in vuex file:
state:{
info:[
{
name: 'Some field 1',
value: '',
pattern: /.+/,
//status: ''
},
{
name: 'Some field 2',
value: '',
pattern: /.+/,
// status: ''
}
]
I would like every object to have a field status: ''.But I do not want to duplicate the code. In Vue component I wrote for this:
beforeMount(){
// add new fuild
}
But this way does not work in Vuex.
beforeMount(){
console.log('does not work');
for (let i = 0; i < this.info.length; i++) {
this.$set(this.state.info[i], 'status', '');
}
}
How to add a new field into state dynamically?
In a mutation just do something like this:
state.info = state.info.map(x => ({
...x,
status: ''
})
I am trying to populate an array from an axios request. The result of the axios request is retrieved by a parent component and its child component populates the table with the data.
Here is what I've done so far :
<script>
import NewSpecification from "../components/NewSpecification";
import SpecificationTable from "../components/SpecificationTable";
export default {
name: "Specifications",
components:{NewSpecification,SpecificationTable},
props: [
'ingredients',
'dishes',
'nutritionalProperties',
'mealPlan'
],
data(){
return{
showNewSpecification: false,
specifications: []
}
},
watch:{
mealPlan:function(){
this.specifications = this.getSpecifications();
}
},
methods:{
getSpecifications(){
var specifications = [];
var restrictedIngredients = this.mealPlan.restricted_ingredients;
restrictedIngredients.forEach(function(item){
specifications.push({
type: "Ingredient",
item: item.name,
meals: this.getStringMeals(item.pivot.breakfast,item.pivot.snack1,item.pivot.lunch,item.pivot.snack2,item.pivot.dinner)
})
});
var restrictedDishes = this.mealPlan.restricted_dishes;
restrictedDishes.forEach(function(item){
specifications.push({
type: "Dish",
item: item.name,
meals: this.getStringMeals(item.pivot.breakfast,item.pivot.snack1,item.pivot.lunch,item.pivot.snack2,item.pivot.dinner)
})
});
var restrictedNutritionalProperties = this.mealPlan.restricted_nutritional_properties;
restrictedNutritionalProperties.forEach(function(item){
specifications.push({
type: "Dish",
item: item.name,
meals: {
breakfast: item.pivot.breakfast,
snack1: item.pivot.snack1,
lunch: item.pivot.lunch,
snack2: item.pivot.snack2,
dinner: item.pivot.dinner
}
})
});
return specifications;
},
getStringMeals(breakfast,snack1,lunch,snack2,dinner){
return (breakfast ? 'Breakfast, ' : '') + (snack1 ? 'Snack 1, ' : '') + (lunch ? 'Lunch, ' : '') + (snack2 ? 'Snack 2, ' : '') + (dinner ? 'Dinner, ' : '')
}
}
}
</script>
However, an error is thrown when I call the method "getStringMeals", and I don't have a clue why I can't access this method from the method getSpecifications().
This is the error thrown in the console:
TypeError: Cannot read property 'getStringMeals' of undefined
Thanks for the help !
In Javascript this acts differently than other languages like Java.
Please read this mdn page.
When you use this inside forEach, it refers to forEach context.
To answer your question, you can store this in a variable:
var self = this;
restrictedDishes.forEach(function(item){
specifications.push({
type: "Dish",
item: item.name,
meals: self.getStringMeals(item.pivot.breakfast,item.pivot.snack1,item.pivot.lunch,item.pivot.snack2,item.pivot.dinner)
})});
Or use fat arrow syntax:
restrictedIngredients.forEach((obj) => {
specifications.push({
type: "Ingredient",
item: item.name,
meals: this.getStringMeals(item.pivot.breakfast,item.pivot.snack1,item.pivot.lunch,item.pivot.snack2,item.pivot.dinner)
})});
Use the arrow function for forEach as shown below.
restrictedIngredients.forEach((obj) => {
specifications.push({
type: "Ingredient",
item: item.name,
meals: this.getStringMeals(item.pivot.breakfast,item.pivot.snack1,item.pivot.lunch,item.pivot.snack2,item.pivot.dinner)
})
})
I wanted to set fields inside data using getters:
export default {
data () {
return {
medications: [],
}
},
computed: {
...mapGetters([
'allMedications',
'getResidentsById',
]),
I wanted to set medications = allMedications, I know that we can user {{allMedications}} but my problem is suppose I have :
medications {
name: '',
resident: '', this contains id
.......
}
Now I wanted to call getResidentsById and set an extra field on medications as :
medications {
name: '',
resident: '', this contains id
residentName:'' add an extra computed field
.......
}
I have done this way :
watch: {
allMedications() {
// this.medications = this.allMedications
const medicationArray = this.allMedications
this.medications = medicationArray.map(medication =>
({
...medication,
residentName: this.getResidentName(medication.resident)
})
);
},
},
method: {
getResidentName(id) {
const resident = this.getResidentsById(id)
return resident && resident.fullName
},
}
But this seems problem because only when there is change in the allMedications then method on watch gets active and residentName is set.
In situations like this you'll want the watcher to be run as soon as the component is created. You could move the logic within a method, and then call it from both the watcher and the created hook, but there is a simpler way.
You can use the long-hand version of the watcher in order to pass the immediate: true option. That will make it run instantly as soon as the computed property is resolved.
watch: {
allMedications: {
handler: function (val) {
this.medications = val.map(medication => ({
...medication,
residentName: this.getResidentName(medication.resident)
});
},
immediate: true
}
}
I am using a simple state manager (NOT vuex) as detailed in the official docs. Simplified, it looks like this:
export const stateholder = {
state: {
teams: [{id: 1, name:'Dallas Cowboys'}, {id: 2, name:'Chicago Bears'}, {id: 3, name:'Philadelphia Eagles'}, {id:4, name:'L.A. Rams'}],
selectedTeam: 2,
players: []
}
getPlayerList: async function() {
await axios.get(`http://www.someapi.com/api/teams/${selectedTeam}/players`)
.then((response) => {
this.state.players = response.data;
})
}
}
How can I (reactively, not via the onChange event of an HTML element) ensure players gets updated (via getPlayerList) every time the selectedTeam changes?
Any examples of simple state that goes a little further than the official docs? Thank you.
Internally, Vue uses Object.defineProperty to convert properties to getter/setter pairs to make them reactive. This is mentioned in the docs at https://v2.vuejs.org/v2/guide/reactivity.html#How-Changes-Are-Tracked:
When you pass a plain JavaScript object to a Vue instance as its data
option, Vue will walk through all of its properties and convert them
to getter/setters using Object.defineProperty.
You can see how this is set up in the Vue source code here: https://github.com/vuejs/vue/blob/79cabadeace0e01fb63aa9f220f41193c0ca93af/src/core/observer/index.js#L134.
You could do the same to trigger getPlayerList when selectedTeam changes:
function defineReactive(obj, key) {
let val = obj[key]
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
return val;
},
set: function reactiveSetter(newVal) {
val = newVal;
stateholder.getPlayerList();
}
})
}
defineReactive(stateholder.state, 'selectedTeam');
Or you could set it up implicitly using an internal property:
const stateholder = {
state: {
teams: [/* ... */],
_selectedTeam: 2,
get selectedTeam() {
return this._selectedTeam;
},
set selectedTeam(val) {
this._selectedTeam = val;
stateholder.getPlayerList();
},
players: []
},
getPlayerList: async function() {
/* ... */
},
};
Your question is also similar to Call a function when a property gets set on an object, and you may find some more information there.
You could use v-on:change or #change for short to trigger getPlayerList.
Here a fiddle, simulating the request with setTimeout.