Change of Global Variable in one component Not reflected in other component in angular2 - angular2-template

In my header component I am declaring a variable this.userFullName = this.globalService.userFullName; & then I am using this variable userFullName in my header template . Now when I change my global variable userFullName from another component (Counsellor Component) this.globalService.userFullName = "Rob" , this change not getting reflected into header template.Why so ? Any alternate solution for implementing this would also be helpful.

Related

Weird Vuejs props behavior with arrays

I created a form component where i pass an object prop to it containing strings and an object array. I then i transfer the elements of the props to the component variables so i can edit them without interacting with the props directly like so:
beforeMount(){
this.var1 = this.props.var1
this.var2 = this.props.var2
this.array = this.props.array
}
when i edit all the other variables, close my component and open it again everything resets BESIDES the array. every time i try to interact with it the reset never happens. i know i am not interreacting directly with the props either in any part of my code so i don't really why this happens when when everything works fine. To fix that i had to do the following:
beforeMount(){
this.var1 = this.props.var1
this.var2 = this.props.var2
this.props.array.forEach(element => {
this.array.push(element)
})
}
why does this work exactly?
I have also been having similar problems with method specific variables not resetting after the function is already over so i find these behaviors a little weird. I am also using "v-if" and also tried to use component keys to reset the component but it doesn't work for the array for whatever reason.
try to copy your array like that :
this.array = [...this.props.array]
I'm not sure about it, but as you pass it within an object, you might actually use you array as reference and not values as you 'd like to.

pass props through template

Is it possible to pass custom config attributes through a template like this?:
<template v-slot:name="{data}" config="myConfig">{{data.field}}</template>
If possible how do I get access to that in the render method?
let a = this.$scopedSlots.name[0]['config']; //something like this
In your example, you pass custom config through props. You can access it in the render method with this.$props.
Take a look at the doc to see how to pass data to child component.

How to access the instance of a component from another component?

In a certain component A, I want to access $refs property (not sure if "property is the right term) of another component B. To do that, I need access to the instance of component B in order to obtain its $refs, sort of like that: instanceOfB.$refs
But how to access instanceOfB, that is, how to access instances of components?
For the record, the code I want to execute injects a new instance of a certain component (Button) into some sibling component (no parent-child relationship), so it's more complicated than simply passing a variable:
import Button from 'Button.vue'
import Vue from 'vue'
var ComponentClass = Vue.extend(Button)
var instance = new ComponentClass()
instance.$mount()
this.$refs.container.appendChild(instance.$el)

Vue multiples components

I'm doing a project with ElementUI Tabs (just HTML and JS files, no .vue files) and I want to open a new Tab, and add html inside, like I've always used to do in Jquery and SemanticUI, for example, the user clicks the menu called "Person" and the Person View (a Vue component) opens in the tab (id = "tab1") to add a new person register, and if the user clicks again the "Person" menu, another tab opens (id = "tab2") with the Person View.
First Question: Because the Vue Component has no "el:" selector, how can I tell to component (Person View) to open inside the "tab1", and another click to open inside the "tab2" ? There is any selector like "el" in Vue.component()?
Second Question: Using Vue instance ( new Vue ({options}) ), it works, because is possible to use the selector "el", but I've read before in some blogs, that is not good practice, because the app must have only one instance of Vue. Is correct add more than one Vue instance ( new Vue () ) as used to be done adding many Vue.component ({}) in the project?
Third Question: I've read before that Vue.component() is a Vue instance, and so would be correct to say that Vue.component() and Vue() is the same thing, but with different sintax ?
Question 1:
Actually, a component does have an el. Your template determines what el is.
For example, I created an inline template for my select2 that look like this:
<select2>
<select></select>
</select2>
Vue.componet("select2", {blah blah blah});
in this case el is the select box directly.
If I did:
<select2>
<div>
<select></select>
</div>
</select2>
the component el would be the div.
Question 2: what you heard from those blogs is nonsense, at least as far as Vue 2 is concerned (never worked with ver 1)
You, as a coder, determine what el is in your code so it is safe to use as a selector. I do it all of the time.
Vues cannot overlap but you can have as many on a page as makes sense. On one set of my tabs, each tab is completely different from each other and independent of each other so each has its own Vue instance. On another, each tab is the same so a made a single component and generated it inside each tab as part of the parent Vue instance.
question 3:
Think of Components as parts and the Vue instance as the whole containing the parts. I personally use components to reduce and compartmentalize code. For example, I have a DataTables component, a select2 component and a tab component, in all cases I have a number of each on each page. Then all I need to do is include them in my Vue instance definition.
After almost two weeks trying, I got it !
First i created an object that has a component structure in a JS file
(personview.js) that i load with requireJS, and pass as a parameter to a
method of Vue Instance called appVue:
appVue.addComponent(componentName,{name:"personview",template:"<div>html tags...</div>",methods:...});
In appVue i added the method:
var appVue=new Vue({
el:'#app',
data() {
return {
components: {},
instances: {}
}
},
methods: {
addComponent(componentName,componentBody){
this.$data.components[componentName]=Vue.component(componentName,Vue.extend(componentBody));
}
}
}
When the user clicks on menu, the method openViewByClickOnMenu is called
and executes:
methods: {
openViewByClickOnMenu(){
//id to identify the components and scripts to load
var componentName="personView"; //for this example i forced the name
//call a method that adds the new tab, and inside the tab adds
//<div id="divX"></div> and return the counter ever increased.
//X in id attribute is the number genereate by the counter
var ctTab=body.addTab({label:menuItem.label});
// will be used to identify an instance of compoment
var componentId=componentName+ctTab; //will be personView1, personView2, etc..
// will be used to identify the div where i want to show component
var divTabId="div"+ctTab;
//load the personview.js with component body
requirejs([componentName],function(){
//creates a new instance of component
app.$data.instances[componentId]=new app.$data.componentes[componentName];
//mounts the component in the div that i want
app.$data.instances[componentId].$mount("#"+divTabId);
});
}
I think the Vue team could add a method in Vue instance to add
components dinamically more easily, sometimes there's no need to
load all html and js files because the user has no acess/permissions
to see some views. And i miss a way to load html native, like
Angular does, because sometimes we need generate html from template engine
inside a SpringBoot for example.

Vue2 Custom Directive modifying component call

I am attempting to write a Vue directive that updates the properties of a component before the component is evaluated.
For example, consider the following.
<b-modal v-i18n:title="'i18n.key'">
Hello
</b-modal>
b-modal is a Vue Component and it takes a property called 'title'. I would like to have a custom directive that can set the property title after translating the supplied key.
That is, I would like the above code to get rewritten by the directive to:
<b-modal title="Translated Text">
Hello
</b-modal>
So far I have read the following resources and found no reference on how to do this.
https://css-tricks.com/power-custom-directives-vue/
http://optimizely.github.io/vuejs.org/guide/directives.html
My current attempt looks like this:
Vue.directive('i18n', {
inserted: function (el,binding) {
const i18nKey = binding.value;
const attrName = binding.arg;
el.setAttribute(attrName, i18nKey);
}
})
This attempt sadly falls short. It results in a change to the final DOM element and has no affect on the property being past to the Vue component.
How can I can the above directive be modified to change the properties being past to the b-modal component?