While using composition API, is there any way to re use props that are common for multiple components? - vue.js

I am trying to migrate a mixin in Vue 2 to composable in vue 3. This mixin was created using class component syntax and all the form UI components (around 30 ) use this mixin. We defined all the common props in this mixin and as a result of that, all those common props were available for all the components that are using the mixin. Can we declare props within composable as well? If not, is there any other way to share reusable props from one commonplace? So that later if we need to change any one prop, we can change from one place instead of making the same change in every component that is using the prop.
import { Prop } from "vue-property-decorator";
import { Inject } from "inversify-props";
// 1: Can we use generic type in composable?
abstract class BaseForm<T> extends Vue{
// 1: This is a common property that all the form components will use
// Also some of the methods defined in this class would use this property
protected item: T = {} as T;
// 2: Common props for all the forms are defined
// Can we declare props composable as well?
// If not, is there any other way to enforce that all my components that are created using composition API
// get this prop from a commonplace?
#prop([required: true, type: Boolean])
protected edit!: boolean;
....
}

Related

How I can get the slot name in which the component is rendered

I want to create a high order component which renders differently depending in which slot the component is. Is there any service where I can get the information in which slot the component is rendered?
You can inject the ancestor PageSlotComponent in your custom component and get the slot name by accessing its public property position$: Observable<string>:
export class CustomComponent {
constructor(#Optional() protected pageSlotComponent: PageSlotComponent) {}
/*...*/
slot$ = this.pageSlotComponent.position$;
}
Explanation:
In Angular you can inject the closest parent component of a given type, by passing it as a constructor dependency.
You might want to add #Optional() decorator if you plan to use your component outside the content slot (i.e. as a static component). It will help avoid crashing app in the runtime, but will just resolve PageSlotComponent instance safely to null.

Any way to make a React presentational component react to MobX store changes

I have a React table component that gets its data via a prop called TableStore. This prop is a high-level abstraction for getting row data:
interface TableStore<RowType> {
getRowIds: () => Array<RowId>;
getRow: (rowId: RowId) => RowType | undefined;
}
interface MaterialTableProps<RowType> {
tableStore: TableStore<RowType>;
}
function MaterialTable<RowType>(props: MaterialTableProps<RowType>) {
...
}
As you can see MaterialTable is not a MobX observer. It is part of a component library that is not dependent on MobX.
When I use this component in my app, I supply it a MobX-based TableStore. I would like the table component to re-render whenever the MobX-based store changes:
<MaterialTable tableStore={orderStore} />
However that does not happen because the table component is not a MobX observer. Is there any way to force the table component to re-render? For example, I am able to force a re-render by dereferencing the store in the parent component (using a simple console.log()). But this feels like a hack. Is there a better way?
Answering my own question....
I looked at several options but all of them were kludgy. I finally decided to rework the props of the table component to pass in an array instead of an abstract TableStore interface (which the table component can't react to). This allowed me to refrain from adding MobX as a dependency to the table component library while still leverage MobX in the parent component. In summary, the parent component now watches the MobX store, reacts to changes by creating a new array and passing it to the table component.
Here's the new interface for the table component:
export interface MaterialTableProps<T extends Entity> extends TableProps {
entityList: Array<T>;
}
export function MaterialTable<T extends Entity>(props: MaterialTableProps<T>) {
...
}

How to define property types when passing props to grandchildren in Vue.js?

I have a Vue component foo inside my HTML and I pass a parameter to it like this:
<foo some="Some String"></foo>
Now inside the foo component I define the property type and default value like so:
export default {
name: "foo",
props: {
some: {
type: String,
default() { return '' }
}
}
}
The foo component's template has another component bar which I pass the some property: <bar :some="some"></bar>.
Now my question is: do I need to again define the type and default value for the some property, this time inside the bar component? So basically copy the props code from the foo component and paste it into the bar component or is there another way?
foo has ensured the type and default value, so there is no need to validate them in bar. If the type were something that has special behavior (e.g., boolean), you would need to specify it, but there's nothing special about string.
Every component instance has its own isolated scope. This means you cannot (and should not) directly reference parent data in a child component’s template. Data can be passed down to child components using props.
Passing data with props
What you need here is to use scoped slot:
Scoped slots allows you to pass props down from Parent components to Child components without coupling them together.

Pass Function as Property to Vue Component

I am trying to make my Vue Component reusable but there is a part in it which requires to run a function on button click which I have defined in the parent component.
The component's button will always run a parent function and the parameter it passes is always the same (its only other property).
Right now I am passing 2 properties to the component: 1) an object and 2) the parent function reference, which requires the object from 1) as a parameter.
The Child-Component looks like this (stripped unnecessary code):
<button v-on:click="parentMethod(placement)">Analyze</button>
Vue.component('reporting-placement', {
props: ['placement', 'method'],
template: '#reporting-placement',
methods: {
parentMethod: function(placement) {
this.method(placement);
}
}
});
The parent is making use of the child like this:
<reporting-placement v-bind:placement="placement" v-bind:method="analyzePlacement"></reporting-placement>
methods: {
analyzePlacement: function(placement) {
this.active_placement = placement;
},
}
As you can see, the child has only one property, placement, and the callback reference. The placement must be put in as a parameter to the reference function from the parent.
But since the parent defines the parameters, the child shouldn't concern itself with what it needs to pass to the parent function. Instead I would prefer to already pass the parameter along in the parent.
So instead of
<reporting-placement v-bind:placement="placement" v-bind:method="analyzePlacement"></reporting-placement>
I would prefer
<reporting-placement v-bind:placement="placement" v-bind:method="analyzePlacement(placement)"></reporting-placement>
(including appropriate changes in the child).
But passing the parameter along does not work that way.
Is it possible (maybe in other syntax) to 'bind' the variable to the function reference so that it is automatically passed along when the callback is called?
Info: I don't get an error message if I write it down as above but the whole Vue screws up when I pass the parameter along to the component.
Hope the issue is clear :-) Thanks a lot!
By reading your proposal I've found out that you are overusing the props passing.
Your concern that child component should not have any knowledge about the way that the parent component uses the data is completely acceptable.
To achieve this you can use Vue's event broadcasting system instead of passing the method as props.
So your code will become something like this:
Vue.component('reporting-placement', {
props: ['placement', 'method'],
template: '#reporting-placement',
methods: {
parentMethod: function(placement) {
this.$emit('reporting-placement-change', placement)
}
}
});
And you can use it like this:
<reporting-placement v-bind:placement="placement" #reporting-placement-change="analyzePlacement($event)"></reporting-placement>
But if you need the data which is provided by the method from parent it's better to consider using a state management system (which can be a simple EventBus or event the more complex Vuex)
And finally, if you really like/have to pass the method as a prop, You can put it in an object, and pass that object as prop.

Two Mixins with same name function Vuejs

Hello I have this problem with vuejs and mixin.
I have a component that has 2 Mixin:
export default {
...
mixins:[Mixin1, Mixin2],
..
}
Both Mixins have a function named "delete", so If in my component I have a method like:
methods:{
deleteObj(){
this.delete()
}
}
I don't know which one function I call.
I know the simplest way is call with a different name the functions but is there a way to specify wich mixin to use?
If you duplicated definitions in methods in mixins, the last mixin will override the previous definitions. In your case this.delete() must called from Mixin2.
But if have lifecycle hooks like mounted, created ... those will be executed one by one in vuejs. There are some strategies followed for merging, vuejs itself you can found more at https://v2.vuejs.org/v2/guide/mixins.html