I want to send an object through props from Main component, to another component (Character.vue).
Character.vue isn't called like a child:
Main.vue has an object called character
<Character :prop="character" />
Character.vue it's a View Component. I want to do some like
Main.vue has a button with an click action:
#click="sendProp"
And the function:
const sendProp = () => {
router.push({
name: "Character",
params: {
character: { ...props.character },
},
});
}
In router I have:
{
path: '/character',
name: 'Character',
props: true,
component: () => import(/* webpackChunkName: "character" */ '../views/Character.vue')
}
I want to execute sendProp function, go to /character route, and get an object in their props.
But when localhost/character is opened by sendProp function, i don't receive the character prop.
Someone can help me? Thanks
Related
A Storybook newbie here. I have an Angular component with a FormControl, which when set to touched, might show an error (depending on the user interaction with the component itself). I've read this: https://storybook.js.org/docs/angular/writing-stories/decorators and tried adding a wrapper for the component which only contained a button. The idea was that user can click a button and thus validate the control inside the component. Didn't happen. Here is my setup:
export default {
title: 'Some title',
component: Component,
decorators: [
moduleMetadata: [...],
componentWrapperDecorator((story)=>`
<div>${story}</div>
<button (click)="doValidate"></button>
`),
]
} as Meta<Component>;
const template: Story<Component> = ( args: Component ) => {
component: Component,
props: args,
methods: {
doValidate(): void {
args.formControl.markAsTouched();
}
}
});
export const validate = template.bind({});
I concur that the method definition is out of place here. So here is the question: how do I trigger/set/mutate something inside a component from that wrapper?
I have this route that has a children. I can retrieve the name of the route however it is only applicable to the name of the children.
const routes = [
{
path: '/',
name: 'Home', // <--- I want to get this route name
component: () => import('layouts/MainLayout.vue'),
children: [
{ path: '', component: () => import('src/pages/Home/Index.vue') },
{ path: '/patient', component: () => import('src/pages/Home/Patient.vue') },
]
},
{
path: '/auth',
name: 'Auth', <--- I want to get this route name
component: () => import('layouts/AuthLayout.vue'),
children: [
{ path: '', component: () => import('pages/Login.vue') },
//{ path: '', component: () => import('pages/Login.vue') }
]
},
// Always leave this as last one,
// but you can also remove it
{
path: '/:catchAll(.*)*',
component: () => import('pages/Error404.vue')
}
]
export default routes
Then I tried remove all named routes from the children and assigned a name to the parent but it gives me
undefined whenever I console.log($route.name) on the MainLayout.vue
I'm not sure if this is really the right way of getting the parent's route name but I have achieved it using route.matched
import { useRoute } from 'vue-router'
...
const path = computed(() => $route.matched[0].name ) //[0] first one
This should return the component name Home
I think you're looking for the immediate parent of the current active route .. yes?
In that case, you do as previously mentioned use this.$route.matched, but not as stated. The current route is the last item in $route.matched array, so to get the immediate parent you can use:
const parent = this.$route.matched[this.$route.matched.length - 2]
const { name, params, query } = parent
this.$router.push({ name, params, query })
In my vue.js 3 project I am using vite-plugin-pages and for some reason #Shulz's solution gives me route.matched[0].name: undefined. So, doing things as mentioned below helped:
In <template>
<router-link to='/the-page' :class='{ "active": subIsActive("/the-page") }'> The Page </router-link>
In <script>
const subIsActive = (input) => {
const paths = Array.isArray(input) ? input : [input];
return paths.some((path) => route.path.indexOf(path) === 0);
};
but, as I am using vite-plugin-pages I found another solution and I followed this approach to fix my issue.
On a List module, I created a bulk action button to generate PDF by calling a custom action.
The problem is <Datagrid> checkboxes are not unselected once the action is executed.
Here is my custom action:
export const print = (resource, ids, data) => ({
type: DOWNLOAD,
payload: {
id: ids.length === 1 ? ids[0] : ids,
data,
},
meta: {
resource: resource,
fetch: PRINT,
onFailure: {
notification: {
body: 'ra.notification.http_error',
level: 'warning',
},
},
},
});
And here is my button:
class PrintBulkButton extends React.Component {
handleClick = () => {
const { basePath, options, print, resource, selectedIds } = this.props;
print(resource, selectedIds, options, basePath);
};
render() {
return (
<Button {...sanitizeRestProps(this.props)} onClick={this.handleClick}>
{this.props.icon}
</Button>
);
}
}
I'm using react-admin 2.3.0, but it wasn't working with previous versions either.
I think the checkboxes are not unchecked because the service I call doesn't update data.
Am I right?
Do I have to call another service or action to uncheck them, or am I missing something?
You can add this onSuccess side effect parameter unselectAll: true that we should document (please open an issue for it):
export const print = (resource, ids, data) => ({
type: DOWNLOAD,
payload: {
id: ids.length === 1 ? ids[0] : ids,
data,
},
meta: {
resource: resource,
fetch: PRINT,
onSuccess: {
unselectAll: true,
},
onFailure: {
notification: {
body: 'ra.notification.http_error',
level: 'warning',
},
},
},
});
Hope someone can advise the best way to achieve what I want.
I have a user grid where you can click edit it then goes to the manage user form.
What I want to do is pass the selected user id over to the manage user form and display this user, how best would I go about achieving this?
Thanks
Andy
In your grid.component.html, when user clicks on a grid edit button, call a function and pass the corresponding grid data id as shown below.
<button (click)="goToManageForm(gridId)"> Edit</button>
In your grid.component.ts, pass the id as a param to the manageForm component.
private goToManageForm(id:any){
this.router.navigate([`/manageForm/${id}`]);
}
In your routing component, add a route to manageForm component which expects a parameter.
const routes: Routes = [
{
path: '',
component: MyMainComponent,
canActivate: [AuthGuard],
children: [
{ path: 'grid', component: GridComponent },
{ path: 'manageForm/:gridId', component: ManageFormComponent },
]
}
You can access the passed grid id in the manageForm.component.ts as shown below.
import { Component, OnInit } from '#angular/core';
import { Router,ActivatedRoute } from '#angular/router';
import { Subscription } from 'rxjs';
export class manageFormComponent {
private subscription:Subscription;
private gridId:any;
constructor(private activatedRoute:ActivatedRoute){}
ngOnInit(): void {
// subscribe to router event
this.subscription = this.activatedRoute.params.subscribe(
(param: any) => {
if(typeof param['gridId'] !== 'undefined' && param['gridId'].trim !='' ){
this.gridId = param['gridId'];
}
});
}
}
Now the passed gridId will be accessible in this.gridId
I've got a component that builds search/sort filters that can be selected. I want the selected state of those filters to be tracked in redux so that the search builder can subscribe and see when they change and update appropriately. the thing I'm trying to figure out how to do (in a way that doesn't feel weird) is populate the filter objects into the state. Eg, right now in the <Search /> component I have something like:
<OptionPicker
group={'searchFilters'}
options={{word: 'price', active: true},
{word: 'distance', active: false},
{word: 'clowns', active: false}}
/>
So how to get those props into state to be used without triggering multiple element renders. I'm also rendering the app on the server as well, so for the initial attachment render, the state already has the options.
In the OptionPicker component I've got:
class OptionPicker extends Component {
constructor(props) {
super(props)
if (!props.optionstate) {
this.props.addOptionState(props)
}
}
render() {
return {this.props.optionstate.word.map((word) => <Option ... />)}
}
}
function mapStateToProps(state, props) {
return {
optionstate: state.optionstate[props.group],
};
}
function mapDispatchToProps(dispatch) {
return {
addOptionState: (props) => {
dispatch(addOptionState(props));
},
optionToggled: (group, word) => {
dispatch(updateOptionState(group, word));
}
};
}
export default connect(mapStateToProps,mapDispatchToProps)(OptionGroup);
This kinda works, but there exists a time when render is called before the redux state has been populated, which throws an error. I could guard against that, but none of this feels "right". Shouldn't that prop always be there? Is there a pattern for this that I'm missing?
I agree with you in that the prop should always be there. The pattern I use for this is to set up an initial state and to pass it to the reducer function:
export const INITIAL_STATE = {
optionstate: { /* all filters are present but deactivated */ }
};
export default function (state = INITIAL_STATE, action) {
// reduce new actions into the state
};