This is a migrated thread and some comments may be shown as answers.

Passing token to Scheduler custom editor form

7 Answers 154 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Daniel
Top achievements
Rank 1
Daniel asked on 14 Apr 2021, 04:24 PM

     Hello everyone,

I've the following code:

render() {
        return (
            <Scheduler
                height={"100%"}
                data={this.state.data}
                onDataChange={this.handleDataChange}
                transport={{
                    token: this.props.token
                }}
                modelFields={{
                    id: "TaskID",
                    title: "Title",
                    description: "Comment",
                    start: "Start",
                    end: "End",
                    recurrenceRule: "RecurrenceRule",
                    recurrenceId: "RecurrenceID",
                    recurrenceExceptions: "RecurrenceException",
                    token: this.props.token
                }}
                editItem={TaskItem}
                form={TaskForm}
                editable={{
                    add: true,
                    remove: true,
                    drag: true,
                    resize: true,
                    edit: true
                }}
                group={{
                    resources: ["Persons"],
                    orientation: "horizontal"
                }}
                resources={[{
                    name: "Persons",
                    data: [
                        {text: "Sascha", value: 35, color: "#5392E4"},
                        {text: "Alex", value: 39, color: "#5392E4"},
                        {text: "Leonhard", value: 54, color: "#5392E4"},
                        {text: "Daniel", value: 91, color: "#5392E4"}
                    ],
                    field: "PersonIDs",
                    valueField: "value",
                    textField: "text",
                    colorField: "color"
                }]}
            >
                <DayView title="Day View"
                         workDayStart={"05:00"}
                         workDayEnd={"20:00"}
                         showWorkHours={true}
                         slotDuration={60}
                         slotDivisions={4}
                />
                <WorkWeekView title="Week View"
                              workWeekStart={Day.Monday}
                              workWeekEnd={Day.Friday}
                              workDayStart={"05:00"}
                              workDayEnd={"20:00"}
                              showWorkHours={true}
                              slotDuration={60}
                              slotDivisions={4}
                />
            </Scheduler>
        );
    }

 

 

And I need to pass a Bearer token property to my form you can see on the code above called TaskForm. So that on the TaskForm with the following code I can get this token on the this.props a pass it to other components. I need this so on many of the child components in this form I can make api calls with axios.

class TaskForm extends Component {
    constructor(props) {
        super(props);
    }
 
    /*const requiredValidator = React.useCallback(
        (value) => (value === undefined || value === null || value === ''
            ? 'Field is required.'
            : undefined),
        []
    );
 
    const formValidator = (_dataItem, formValueGetter) => {
        let result = {};
 
        result.Patient = [
            requiredValidator(formValueGetter('Patient'))
        ].filter(Boolean).reduce((current, acc) => current || acc, '');
 
        result.Treatment = [
            requiredValidator(formValueGetter('Treatment'))
        ].filter(Boolean).reduce((current, acc) => current || acc, '');
 
        return result;
    };*/
    componentDidMount() {
        console.log(this.props);
    }
 
    render() {
        return (
            <SchedulerForm
                {...this.props}
                editor={TaskFormEditor}
                dialog={TaskDialog}
                /*validator={formValidator}*/
            />
        );
    }
}
 
export default TaskForm;

7 Answers, 1 is accepted

Sort by
0
Stefan
Telerik team
answered on 15 Apr 2021, 06:15 AM

Hello, Daniel,

This can be done by adding a custom onSubmit event:

https://www.telerik.com/kendo-react-ui/components/scheduler/api/SchedulerFormProps/#toc-onsubmit

This will allow intercepting the submit event, make a custom request to the server which will allow adding any tokens to the server:

https://stackblitz.com/edit/react-4xwgyv?file=app/custom-form.jsx

I hope this is helpful.

Regards,
Stefan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Daniel
Top achievements
Rank 1
answered on 15 Apr 2021, 09:58 AM

Hello Stefan,

Thank you very much for your help :D

I've seen your post and need to understand how I could do it.

Actually what I want is to pass a property to my scheduler, a token, that I could get inside the editor of the SchedulerForm component.

I would like to make Api calls to fill the editor dialog components here:

import React, {Component} from "react";
 
import {FormElement, Field} from '@progress/kendo-react-form';
import {Label, Error} from '@progress/kendo-react-labels';
import {TextArea} from '@progress/kendo-react-inputs';
import {DateTimePicker} from '@progress/kendo-react-dateinputs';
import {TaskTemplatesEditor} from "./Editors";
import ProjectsEditor from "./ProjectsEditor";
import VehiclesEditor from "./VehiclesEditor";
 
class TaskFormEditor extends Component {
    constructor(props) {
        super(props);
    }
 
    componentDidMount() {
        //AjaxCallHere with axios!!!
        //And need to access the token here comming from the props
    }
 
    render() {
        return (
            <FormElement horizontal={true}>
                <div className="k-form-field">
                    <Label>
                        Project
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Project"}
                            component={ProjectsEditor}
                        />
                        {/*{props.errors.Patient && <Error>{props.errors.Patient}</Error>}*/}
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Vehicle
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Vehicle"}
                            component={VehiclesEditor}
                        />
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Task Template
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Task Template"}
                            component={TaskTemplatesEditor}
                        />
                        {/*{props.errors.Treatment && <Error>{props.errors.Treatment}</Error>}*/}
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Note
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Comment"}
                            component={TextArea}
                            rows={1}
                        />
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Start
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Start"}
                            component={this.props.startEditor}
                            as={DateTimePicker}
                            rows={1}
                            format="t"
                        />
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        End
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"End"}
                            component={this.props.endEditor}
                            as={DateTimePicker}
                            rows={1}
                            format="t"
                        />
                    </div>
                </div>
            </FormElement>
        );
    }
}
 
export default TaskFormEditor;

 

i'll try to do something with your info too.

Thanks again,

Best Regards,

Daniel

0
Accepted
Stefan
Telerik team
answered on 15 Apr 2021, 10:47 AM

Hello, Daniel,

Thank you for the clarification, I assume that the token needs to be added when the Form is submitted.

If the request will be made to populate the Form, then indeed the componentDidMount event can be used to make the request.

If you want to pass the token as a prop, I can suggest using React.Context which will allow passing props between components, and you will have access to the token where it is needed:

https://reactjs.org/docs/context.html

Regards,
Stefan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Daniel
Top achievements
Rank 1
answered on 15 Apr 2021, 11:02 AM

Hello Stefan,

Thank you very much for your help. I'm not a React expert :D

Didn't know about this, thanks.

Will try it.

0
Daniel
Top achievements
Rank 1
answered on 15 Apr 2021, 12:33 PM

Hello again Stefan,

I'm not managing to add the token to the context and retrieve it back on a child component. Here's my code as far as I've seen:

import React, {Component} from "react";
import ReactDOM from 'react-dom';
import {BrowserRouter as Router} from 'react-router-dom';
import Navbar from "./Navbar";
import Body from "./Body";
import "@progress/kendo-theme-default/dist/all.css";
 
const TokenContext = React.createContext("token");
 
class Root extends Component {
 
    constructor(props) {
        super(props);
        this.state = {
            user: {}
        };
    }
 
    render() {
        return (
            <div className="box">
                <Router>
                    <TokenContext.Provider value={this.props.token}>
                        <Navbar user={this.state.user}/>
                        <Body userId={this.props.userId} token={this.props.token}/>
                    </TokenContext.Provider>
                </Router>
            </div>
        );
    }
}
 
Root.contextType = TokenContext;
export default Root;
 
if (document.getElementById("root")) {
    const rootElement = document.getElementById("root");
    const userId = rootElement.getAttribute("data-user-id");
    const token = rootElement.getAttribute("data-token");
    ReactDOM.render(<Root userId={userId} token={token}/>, document.getElementById("root"));
}

 

On my Body component or on the Navbar component, in the componentDidMount function, I'm calling console.log(this.context) and it returns an empty object.

Can you provide aditionall help?

Thank you.

0
Daniel
Top achievements
Rank 1
answered on 15 Apr 2021, 12:47 PM

Hello Stefan,

I managed to make it work.

I created a Context.jsx file with the following code:

import React from "react";
 
export const TokenContext = React.createContext("token");

 

Then on my Root component I have:

render() {
        return (
            <div className="box">
                <Router>
                    <TokenContext.Provider value={this.props.token}>
                        <Navbar user={this.state.user}/>
                        <Body userId={this.props.userId} token={this.props.token}/>
                    </TokenContext.Provider>
                </Router>
            </div>
        );
    }

 

And then on the component I want the token in I have:

import React, {Component} from "react";
 
import {FormElement, Field} from '@progress/kendo-react-form';
import {Label, Error} from '@progress/kendo-react-labels';
import {TextArea} from '@progress/kendo-react-inputs';
import {DateTimePicker} from '@progress/kendo-react-dateinputs';
import {TaskTemplatesEditor} from "./Editors";
import ProjectsEditor from "./ProjectsEditor";
import VehiclesEditor from "./VehiclesEditor";
import {TokenContext} from "./Context";
 
class TaskFormEditor extends Component {
    constructor(props) {
        super(props);
    }
 
    // This line of code is making all the difference, I'm associating the
    // context of this component with the context I created!!! :D
    static contextType = TokenContext;
 
    componentDidMount() {
        console.log(this.context);
    }
 
    render() {
        return (
            <FormElement horizontal={true}>
                <div className="k-form-field">
                    <Label>
                        Project
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Project"}
                            component={ProjectsEditor}
                        />
                        {/*{props.errors.Patient && <Error>{props.errors.Patient}</Error>}*/}
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Vehicle
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Vehicle"}
                            component={VehiclesEditor}
                        />
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Task Template
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Task Template"}
                            component={TaskTemplatesEditor}
                        />
                        {/*{props.errors.Treatment && <Error>{props.errors.Treatment}</Error>}*/}
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Note
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Comment"}
                            component={TextArea}
                            rows={1}
                        />
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        Start
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"Start"}
                            component={this.props.startEditor}
                            as={DateTimePicker}
                            rows={1}
                            format="t"
                        />
                    </div>
                </div>
                <div className="k-form-field">
                    <Label>
                        End
                    </Label>
                    <div className="k-form-field-wrap">
                        <Field
                            name={"End"}
                            component={this.props.endEditor}
                            as={DateTimePicker}
                            rows={1}
                            format="t"
                        />
                    </div>
                </div>
            </FormElement>
        );
    }
}
 
export default TaskFormEditor;

 

And now on the componentDidMount I can get the token and make my api calls with no problem.

Thank you again.

 

Best Regards,

Daniel

0
Stefan
Telerik team
answered on 16 Apr 2021, 06:03 AM

Hello, Daniel,

I`m glad to hear that this is working now.

Also, thank you for sharing the solution with the KendoReact community it is highly appreciated.

Regards,
Stefan
Progress Telerik

Тhe web is about to get a bit better! 

The Progress Hack-For-Good Challenge has started. Learn how to enter and make the web a worthier place: https://progress-worthyweb.devpost.com.

Tags
General Discussions
Asked by
Daniel
Top achievements
Rank 1
Answers by
Stefan
Telerik team
Daniel
Top achievements
Rank 1
Share this question
or