Passing data from template to component - vue.js

I have the following, which for my understanding should pass the value of html attribute to the #Prop with the same name however my console.log is always undefined. How is this accomplished?
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
#Component({})
export default class RelayComponent extends Vue {
#Prop([String]) service: string;
constructor() {
super();
console.log(this.service);
...
HTML
<template>
<div service="expecting this value passed"></div>
</template>
<script src="./relay.ts"></script>

Vue props
Vue props are intended to pass data from a parent vue component or instance to a child vue component.
So you have a vue component, you set up a #Prop and then you get the prop for the html of the parent. Should you have a my-parent and my-child components, the my-parent template could be:
<template>
<my-child count="7"></my-child>
</template>
So a child component like this:
<template>
<div class="counter">{{count}}</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
#Component({})
export default class myChild extends Vue {
#Prop() count: number;
}
</script>
Would get 7 as its count prop.
Now, in your case, there is only one component, and you're trying to setup the service variable of the component from the HTML. This is sort of weird because the point of Vue is to achieve declarative rendering from the component data: is the HTML who reacts to data changes, not your component who gets data from the HTML.
(Of course, you can also setup v-model and event listeners to make your components react to user input, but that's another story).
Basically, if I understood correctly what you want to do, your issue is that you're trying to get the service prop from the HTML of the very RelayComponent component.
Instead, you should setup the service prop in the component parent:
// Code of some parent component that renders the RelayComponent
<template>
<relay-component service="this would set the service prop as a string"></relay-component>
</template>
Only, when dealing with objects, you usually don't pass down a plain string, but a javascript object, and a service variable probably is an object, so changes are you're behind something like this:
<template>
<relay-component v-bind:service="serviceVariableInTheParentComponent"></relay-component>
</template>
Where the parent component has a service variable in its data.
 Constructor and lifehooks
Be wary about explicitly calling constructor in vue class components. If you modify the component state in the constructor, you can break the component.
Probably, you should consider to ever use the created() lifecycle hook instead of constructor() in every Vue component.

Related

Does defineProps in script setup automatically create a local property of the defined prop?

When we pass a prop to a component and define that prop from child component with defineProps a property somehow is created and accessible from child components template.
parentComponent.vue
<template>
<child-component v-model="product">
</template>
<script setup>
import childComponent from "./childComponent.vue"
</script>
childComponent.vue
<template>
{{ product }}
</template>
<script setup>
const props = defineProps(['product'])
</script>
Here in childComponents template, the product can be accessed without needing to use props.product or toRef it. I know that script setup automatically injects the used props but I could not find any info (in docs) that the defineProps does some too. Is there any info about that.
According to this section :
The script is pre-processed and used as the component's setup() function, which means it will be executed for each instance of the component. Top-level bindings in <script setup> are automatically exposed to the template. For more details
Knowing that props are unwrapped directly inside the template and also the refs are used without .value.
If you want to reference some prop inside the script you should use props.product like in this example :
<script setup>
const props = defineProps(['product'])
const total=computed(()=>props.product.quantity*props.product.unity_price))
</script>
if the prop is only accessed by template you could get rid off const props just call the macro defineProps :
<template>
{{ product }}
</template>
<script setup>
defineProps(['product'])
</script>

How to make a Base component that will allow other components to inherit new functionality or code from it in Vue JS

Component 1:-
<template>
<blur :isData="isData">
<!-- logic/implementation of component 1 -->
<div>
</div>
</blur>
<template>
<script>
import blur from "../shared/Blur";
name: "component-1",
components: {
blur,
},
</script>
Just like this component1.vue, I have multiple components which are using blur component. Is it possible that instead of writing and importing blur in every single component, I can make some base class that can transfer the blur functionality in every single component in the folder. Can something like this be achieved in vue ?
With Vue.component you can create globally registered components:
Vue.component('my-component-name', {
// ... options ...
})
Find out more here

VueJS extend component for customization

Is there any way to use some Generic component and keep it's props emitters etc and just customize it?
Example:
<template>
<GenericComponent color="black">
Something in the default slot
</GenericComponent>
</template>
<script>
import GenericComponent from 'GenericComponent'
export default {
name: 'MyCustomizedComponent'
props: // to take same props as GenericComponent and pass it to GenericCompnent?
// and it emits all events from GenericComponent
// I could probably just copy props and pass it directly to GenericComponent, but what if there
// is many
}
</script>
<style scoped>
//some changes to Generic component
<style>
So I could just create props, and define all # from GenericComponent and emit them same way, but is there any easy way to do it ?
You can either use mixins, to reuse code across several components.
You can also create a wrapper component to the original component, do your customizations, and use v-bind="$props" to propagate all props to the original component and v-on="$listeners" to emit all events from the original component to the parent.
I'm not sure what is best for your case.

How do I access v-model in vue-class-component

I want to use the new Vue syntax from https://github.com/vuejs/vue-class-component. Unfortunately, I have trouble accessing the value that's passed with v-model. I can instead declare a #value property to pass the value but that seems a bit inconsistent given that there are a lot of existing uses of v-model in my codebase.
<template>
<div>
{{value}}
</div>
</template>
<script lang="ts">
import Vue from "vue"
import Component from "vue-class-component"
import { Prop } from "vue-property-decorator"
#Component
export default class Display extends Vue {
#Prop() value!: string
// lifecycle hook
mounted() {alert("The value is " + this.value)}
}
</script>
The current code can be accessed with:
<Display :value="myVar"/>
I'd like to access via:
<Display v-model="myVar"/>

VueJS - Generating html string of a component in computed property

I'm looking for a suggestion regarding a cleaner approach to generate a component data as html string and to pass it raw through the props of the component.
component-a.js
import componentB from './component-b'
computed: {
tooltipHTML() {
render "<componentB :name='user1'/>
}
}
I would prefer something similar to the above idea.
Generating HTML in a computed property and passing it as props to another component to be rendered in that component will not work.
What you are looking for is Slots
Since the complete code is not provided I guess you wanted to render <componentB :name='user1'/> inside another component( a tooltip component)
You would be doing it as follows using slots:
<tooltip-comp>
<componentB :name='user1'/>
</tooltip-comp>
In your tooltip component
//tooltip component
<template>
<div class="my-tooltip">
<p>my tooltip</p>
<slot></slot>
</div>
</template>