Vue2 component as <vue-component>value</vue-component> - vue.js

It is possible to pass a value to the component between the component tags?
Example: in a component to format value to money, I created as :
<vue-component value="50" />
and it display
$ 50,00
Now, just for curiosity, it is a way to call the component like these:
<vue-component>50</vue-component>

Read about slots: vuejs.org/v2/guide/components-slots.html
Fe: <template><h1><slot/></h1></template>
You can access ita value via: this.$slots.default[0].text
The fact that it's possible doesn't mean that you should do it. Actually, on the contrary. Props have multiple advantages (such as marking as required, default value, validators and many more) but in thr first place they are standardised way of passing data to children components every vuejs developer will understand.

Related

Create component in template from data variable

I have multiple components that take same props. I want to use those components in template in such a way that I don't use multiple if-else statements in my template. I created an object in my data and paired my components with string keys. Is there a way to call those components in template with that object ? My data object looks something like this:
componentMap:{
"testComponent1":TestComponent1,
"testComponent2":TestComponent2,
},
For example, if I give "testComponent1" as key, then in template it should use TestComponent.
Use the component tag.
<component :is="componentMap['testComponent1']"></component>
See the Docs

Vue js - is that right to put all my code in watch?

I Have component A and Component B
in component A i have an API call.
when i passing info to my component b:
<B :structuresMetaData="structureTree"></B>
Inside mounted the variable structuresMetaData the length is 0
and inside the watch the length is 1.
my issue that mounted appear before the watch.
is it would be right to put all my code in watch ? if not what is the solution ?
It looks like structureTree is being changed after <B> is created/mounted.
You have two options depending on your use case:
The first option is to defer the creation of <B> until your data is loaded. This way you don't need <B> to watch for changes to the prop and the prop will be fully populated in the created/mounted hook. This is the simpler approach.
Assuming structureTree is initially an empty array:
<B
v-if="structureTree.length > 0"
:structuresMetaData="structureTree"
/>
created() {
// this.structuresMetaData is a non-empty array here
}
I usually initialize my data with null so that I can distinguish between "not loaded" and "loaded" (where "loaded" can actually be an empty array if the data I fetched from the API was empty).
The second way is using a watcher in <B> to react to changes to the prop. You will need to do this method if the bound prop might change multiple times and you need <B> to update in some way to that change.
watch: {
structuresMetaData(value) {
// React to the change, load secondary data, etc
}
}
What exactly are you doing in <B> that requires a watcher? It's best to avoid explicit watchers if you can avoid them because it usually means you are copying data around and it gets messy when you don't have a single source of truth. Use pure computed properties whenever you can if you just want to transform the data in some way.

react-select: How can I use the optionRenderer prop with the Async component?

I am using react-select to make a select box that geocodes an address and then provides a drop down list of the corresponding local government areas of that search returns.
I am just trying to format each option so it shows the State eg. Queensland after the local government area eg. Brisbane.
So I'm trying to get it to return something like:
Brisbane <small>Queensland</small>
But in the HTML it escapes and renders the tags.
It looks like optionRenderer would work, but it seems to be only available with the Select component of react-select and I am currently using Async because I want to wait for the geocoded latitude and longitude from Mapbox.
Anyone know a way to format options while using the <Async /> component?
OK so I worked out what I was doing wrong. The optionRenderer={this.renderOption} prop was working after all but I was returning a string instead of a JSX component.
So here's my method anyway for anyone who has this issue in the future:
renderOption(option) {
return <div> {option.label} <small>small</small></div>;
}
So I'll just need to split the option.label up and put the State in between the tags.

Pass data between extended components OR call method of component

I have main component which fetch list of users in Created() method. Two next components extended of main component. In this case created method calls each time at extended components created. So i have extra call of fetch list of users. Goal is fetch users one time and pass it to extended components.
For example:
https://jsfiddle.net/apokjqxx/45/
In example we can see that Created() method of main components called two time but need one time and pass data to extended components. What's best solution for this?
Each extended component is a different object instance, that's why Created() and fetch are been executed twice.
What you need is another piece of code acting like a storage (cache) for your item's list, this piece of code should be instantiated once and shared among your components.
Vuex is probably a good option for that "piece of code"
If your math and physics component share the same data, and even have a lot in common in template, why not make them one component? This will solve your duplicated fetch issue, and you can easily rearrange your template by wrapping your current template with a v-for and use
data() {
return {
lists: [
{course: 'math', people: ['mike', 'arnold', 'tony']},
{course: 'physics', people: ['mike', 'arnold', 'tony']}
]
};
}
as your data.

VueJS Component Input Sync

I want to create components which have input which two-way bind to the local scope of the component.
Without a component, I would create a new Vue instance and then set my data to what I need. Then using v-model, bind an input to that data and it can be manipulated from the input.
However, converting the same code to a component, I cannot for the life of me get any input in a component to bind to its data. I have tried props, :data.sync, data attributes but no matter what I have tried, the input within a component does nothing.
I have created a JSFiddle to illustrate this:
https://fiddle.jshell.net/f0pdmLhy/2/
What I would like to happen is the input in the component to two way bind to the err variable, just like the non component version underneath.
How would I accomplish this?
I basically want to create components that I can instansiate with ajax data and then populate the inputs. The inputs could then update the data and I can use a save method to send the data to the server. Can this even be done using components?
So there are a couple of things:
The external resource you were using was somehow faulty. I've used
jsfiddle default Vue instance and it works fine.
When you declare a component, you should not define the data as an object, but as a function returning an object. Read here: https://vuejs.org/guide/components.html#Component-Option-Caveats
A working example here: https://fiddle.jshell.net/by4csn1b/1/
Yes, with components, the reactivity can be accomplished just like with an instance.
One catch with components, is that data must be a function that returns an object.
Also, to maintain the two way binding, use v-model in your input.
Vue.component('ii', {
template: '<span>{{err}}</span><input type="text" v-model="err"><hr>',
data: function () {
return {
err: 123
}
}
})
Fiddle: https://fiddle.jshell.net/f0pdmLhy/25/