Grid Collumn Template with React+Redux

7 posts, 0 answers
  1. Akhmad Agosto
    Akhmad Agosto avatar
    12 posts
    Member since:
    Oct 2017

    Posted 29 Nov 2017 Link to this post

    I am using React+Redux along with React wrappers for the Kendo UI Grid component. Here's a crop of my code:

    import React, { Component } from 'react'
    import { Grid } from '@progress/kendo-grid-react-wrapper';
     
    class InputOrderComponent extends Component {
        
        static propTypes = {
            ...
            actionAdd: PropTypes.func,
            ...
        }
        render() {
            const { inputOrder, actionSelect, listBranch, actionChange, actionAdd, actionRetrieveBranch,  } = this.props;
             
            return (
               .....
               <Grid
                                        dataSource={new kendo.data.DataSource({
                                            transport: {
                                                read: function(e){
                                                    actionRetrieveBranch()
                                                    .then(res =>{                                              
                                                        e.success(res)
                                                    })                                           
                                                }
                                            },
                                        })}
                                         
                                        filterable={true}
                                        sortable={true}
                                        groupable={false}
                                        pageable={true}
                                        columns={[
                                            {title:"No", filterable: false, template: '#='+ ++record  +'#', width:44},
                                            {field:"branchCode", title:"Part Number"},
                                            {field:"branchDescription", title:"Part Description"},
                                            {field: "phone1", title:"HET", width:100},
                                            {field: "branchCode", title:"Action", width:120, template:"<button onClick=\"actionAdd.bind(this,'branchCode')\" type='button' class='k-button k-button-icontext'><i class='fa fa-plus-circle' style='margin-right: 5px'></i> Pilih</button>"},
                                        ]}
                                        dataBinding={function() {
                                            //this.setState({
                                                //record : (this.dataSource.page() -1) * this.dataSource.pageSize()
                                            //})
                                            console.log(this.dataSource.data())                                
                                        }
                                        }
                                    />
                     ....
             )
        }
    }

    I'm having diffucilties having my onClick action recognized. While the onClick event does trigger, the actionAddaction isn't. It throws a "Uncaught ReferenceError: actionAdd is not defined
        at HTMLButtonElement.onclick (inputOrder:1)" error.

    Is this related to how the documentation mentions that react components are not supported in templates? I'm also having difficulties replicating this documentation on how to add Row Numbers. Records, in the template, throws an undefined error just like the above, unless I initialize the record variable outside the main component class.

    Help would be appreciated.

  2. Stefan
    Admin
    Stefan avatar
    3012 posts

    Posted 01 Dec 2017 Link to this post

    Hello, Akhmad,

    Indeed both issues occur because the templates do not have access to the React component. The main reason is that these are jQuery templates, and the concept of React components was still not available at the time of the implementation. This should work out of the box with our pure React widgets expected in R1 2018.

    In this scenario, I can suggest adding a button, then on the dataBound event to attach event listener which will call the React function.

    As for the number column, the variable can be attached to the window scope inside the constructor and then called in the template.

    I made an example demonstrating both implementations:

    http://dojo.telerik.com/iKaPa/2

    I hope this is helpful.

    Regards,
    Stefan
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Akhmad Agosto
    Akhmad Agosto avatar
    12 posts
    Member since:
    Oct 2017

    Posted 04 Dec 2017 in reply to Stefan Link to this post

    Thank you!

    The above solutions do work. I have another question though, how do I retrieve the item in which the click() event was triggered on? I need to retrieve the data on the specific record that was clicked (ie: ProductName, UnitPrice, etc), but both (e) and (this) paramaters return the whole grid object containing the grid item list. I couldn't find a way to get the event triggered specific item's index or anythign simillar.

  4. Stefan
    Admin
    Stefan avatar
    3012 posts

    Posted 04 Dec 2017 Link to this post

    Hello, Akhmad,
     
    I'm glad to hear that the provided example works as desired.

    As for the row data - this could be achieved by retrieving the row dataItem on the click event of the button and passing that dataItem to the React function.

    I updated the Dojo example to demonstrate this:

    http://dojo.telerik.com/iKaPa/4

    someReactFunction = (dataItem) => {
             console.log(dataItem)
    }
     
     onDataBound = (e) => {
       var that = this
             $('.details').click(function(event){
               var row  = $(this).closest('tr');
               var dataItem = e.sender.dataItem(row)
               that.someReactFunction(dataItem)
             })
     }


    Regards,
    Stefan
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  5. Akhmad Agosto
    Akhmad Agosto avatar
    12 posts
    Member since:
    Oct 2017

    Posted 05 Dec 2017 in reply to Stefan Link to this post

    Thank you Stefan, you've been a great help. I do have more questions, if you don't mind:

    I am using a custom API to directly bind the grid's dataSource. However because I'm also updating states using React+Redux handlers in the same page, everytime I trigger a state change the grid will re-render and thus re-firing the API everytime due to the autoBind option being true by default. Since I'd like to bind and fire the grid's API manually from a custopm button, turning the autoBind option off seems like the best solution to avoid the API-refiring on every render issue. However I can't find a way to fire the fetch() method to the dataSource manually. Targeting the grid element by Id like I'd usually do in jQuery / AngularJS doesn't seem to work.

    Help would be appreciated.

     

  6. Akhmad Agosto
    Akhmad Agosto avatar
    12 posts
    Member since:
    Oct 2017

    Posted 06 Dec 2017 Link to this post

    Never mind the question above, I already worked around it by making the dataSource bind to a local data which is managed by a state and API hanlder. So no issues there.
    I am now trying to bind a react function/state handler to the Kendo Grid's included increase and decrease (numeric textbox component, on editable set to true settings) buttons, but can't seem to find the appropriate event listener or class target to it.
    $('k-link-increase').click(...)

    The above doesn't work to catch the increase/decrease button event. 

    I did notice that the included numeric textbox is the same as the one in the standalone React Wrapper component, and that has the spin and change events. Though that is a component by itself, and the one included in the grid doesn't seem to have it's own accessible event properties since it's supposedly included inside the template. But the template itself doesn't support react components right? So I'm quite confused here.

    I think using jQuery event listeners is the correct way to do it, but can't seem to find out how.

  7. Stefan
    Admin
    Stefan avatar
    3012 posts

    Posted 06 Dec 2017 Link to this post

    Hello, Akhmad,

    I'm glad to hear that the suggestions were helpful.

    In the NumericTextBox scenario, this is indeed the standalone NumericTextBox widget, it is used in the template as it is a wrapper and it is just a jQuery widget, not an actual React component.

    I can suggest the Edit event of the Grid to locate the numeric textbox widget and to bind to its spin event:

    onEdit = (e) => {
          var numeric = $(e.container).find('[data-role="numerictextbox"]').data('kendoNumericTextBox')
          if(numeric !== undefined){
           numeric.bind("spin", function(e) {
            console.log("spin event handler");
          });
        }
    }

    https://docs.telerik.com/kendo-ui/intro/widget-basics/events-and-methods#event-binding-after-initialization

    https://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-edit

    http://dojo.telerik.com/ozeyAz

    Also, please have in mind that we will appreciate if a separate ticket is submitted when the new question is not directly related to the first one, as this is helping us to determine which scenarios are most commonly used and based on that to improve the documentation in that direction.
     
    Regards,
    Stefan
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top