jQuery UI Widgets Forums React How to pass the jqxgrid success response to parent component ! Urgent

This topic contains 5 replies, has 2 voices, and was last updated by  Hristo 6 years, 5 months ago.

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author

  • sonu
    Participant

    Hi. I’m using the react 16 with jqwidget and i have create a page where a dropdown with selected default value and in child based on dropdown i will call a jqxgrid from the url . things are working fine but there is one issue when data is still loading in the grid user can change the dropdown value so the server load is high . The previous request is not completed and user change the dropdown so i have disable the option value in dropdown and when the data adapter result is come i will update the state with true so it will again enabled the dropdown. But issue is when i call the handleDisabled function of parent and in parent handleDisabled i’m trying to setState but state is not set with the warning.

    Warning: Can’t call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

    Please help me and lookat my file whether the wrong approach i’m using or any other way to do this thing so that user is not change the dropdown value until the result is success.

    These are my files .

    AdvancedSearch.js
    
    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    //import Leftmenu from '../include/leftmenu';
    //import { FormControl } from 'react-bootstrap';
    import 'react-datepicker/dist/react-datepicker.css';
    import { Jqgrid } from './jqgrid';
    import '../css/custom_grid.css';
    //import statusDoc from '../config/status';
    //import Gridsample from './gridSample';
    //import JqxListBox from '../assets/jqwidgets-react/react_jqxlistbox.js';
    import SelectMenu from './components/selectMenu';
    import filters from '../config/filters';
    
    export default class AdvancedSearch extends Component {
    
        constructor() {
            super();
    
            let defaultData = this.findObjectByKey(filters, 'default', true);
    
            this.state = {
                retailer_id: [1, 2, 4, 5, 12, 20, 23, 24],
                //store_id: [903],
                is_sandbox_on: [0],
                status: [],
                // pagenum: 0,
                // pagesize: 10,
                dataDetails: [],
                conditions:defaultData.conditions,
                selectFilter: [defaultData.name],
                isFilterChange: false,
                letmedebug: 0,
                isDisabled:false
            };
            this.handleClickDropdown = this.handleClickDropdown.bind(this);
    
        }
    
        findObjectByKey(array, key, value) {
            for (var i = 0; i < array.length; i++) {
                if (array[i][key] === value) {
                    return array[i];
                }
            }
            return null;
        }
    
        handleClickDropdown(event) {
            //console.log(event.target.value);
            let data = this.findObjectByKey(filters, 'name', event.target.value);
            //console.log(data);
    
            this.setState({ isFilterChange: true });
            this.setState({ conditions: data.conditions });
            //this.setState({ status: statusDoc[event.target.value]['status'] });
            this.setState({ selectFilter: [event.target.value] });
            //this.setState({ isDisabled: true });
        }
    
        handleDisabled(val)
        {
            this.setState({isDisabled:val});
            console.log("ods "+val);
        }
        
    
        render() {
    
            const dropdownStyle = {
                marginTop: '25px',
                marginRight: '-20px',
                width: '250px'
            };
    
            const buttonStyle = {
                marginTop: '25px',
                marginRight: '-20px',
                width: '120px'
            };
            const buttonRightStyle = {
                fontSize: '20px',
                marginTop: '30px',
                float: 'right',
                marginLeft: '-120px',
                width: '85px'
            };
            //console.log("call two times");
            return (
    
                <section className="body-content-section">
                    <div className="container">
                        <div className="row content-section">
                            <div className="col-lg-11 col-md-11 col-sm-11 main-content-section">
                                <div className="row">
                                    <div className="row">
    
                                        <div className="col-md-4 col-xs-12 form-group" style={dropdownStyle}>
                                            <SelectMenu action={this.handleClickDropdown} params={filters} defaultValue={this.state.selectFilter[0]} isDisabled={this.state.isDisabled}/>
                                        </div>
    
                                        <div className="col-md-2 col-xs-12 form-group" style={buttonStyle}>
                                            <button type="submit" className="btn btn-default search-btn"><i className="fa fa-floppy-o"></i> Save</button>
                                        </div>
    
                                        <div className="col-md-2 col-xs-12 form-group" style={buttonStyle}>
                                            <button type="submit" className="btn btn-default search-btn"> <i className="fa fa-pencil-square-o" aria-hidden="true"></i>  Save As </button>
                                        </div>
    
                                        <div className="col-md-2 col-xs-12 form-group" style={buttonRightStyle}>
                                            <i className="fa fa-download img-space" aria-hidden="true"></i>
                                            <i className="fa fa-columns" aria-hidden="true"></i>
                                        </div>
                                    </div>
                                    <hr />
                                </div>
    
                                <div className="row" >
                                    {/* {this.state.isFilterChange ? <Jqgrid params={this.state} /> : <div className="bold sf-align-center">No Record Found</div>} */}
                                    <Jqgrid params={this.state} handleDisabled={this.handleDisabled.bind(this)} />
                                </div>
                                <br />
    
                            </div>
    
                            <div className="search-loading-img"></div>
    
                        </div>
                    </div>
                </section>
    
            );
        }
    }
    ReactDOM.render(<AdvancedSearch />, document.getElementById('root'));
    // if (document.getElementById('search')) {
    //     ReactDOM.render(<AdvancedSearch />, document.getElementById('search'));
    // }

    SelectMenu.js

    import React, { Component } from 'react';
    import { FormControl } from 'react-bootstrap';
    
    export default class SelectMenu extends Component {
    
        render() {
            let filters = this.props.params;
    
            const listItems = filters.map((e, key) =>
            <option key={e.id} value={e.name}>
              {e.label}
            </option>
          );
    
            let defaultValue = this.props.defaultValue;
            console.log(defaultValue);
            
            return (
                
                <FormControl componentClass="select" placeholder="select" disabled={this.props.isDisabled} onChange={this.props.action} defaultValue={defaultValue} disabled={this.props.isDisabled}>
                    <option value="select">Select filter</option>
                    {
                        //dsfsd
                        listItems
                    })
                    }
            </FormControl>
            );
        }
    
    }

    Jqgrid.js

    import React, { Component } from 'react';
    import 'jqwidgets-framework/jqwidgets/styles/jqx.base.css';
    import 'jqwidgets-framework/jqwidgets/jqx-all';
    import JqxGrid, { jqx } from '../assets/jqwidgets-react/react_jqxgrid';
    import statusDoc from '../config/status';
    import Config from '../config/config';
    
    export class Jqgrid extends Component {
    
        constructor(props) {
            super(props);
            let letcheck = this;
            //console.log(this.props.params);    
            let source =
                {
                    datafields:
                        [
                            { name: 'id', type: 'number' },
                            { name: 'last_name', type: 'string' },
                            { name: 'item_descriptor', type: 'string' },
                            { name: 'repairer_name', type: 'string' },
                            { name: 'product_brand', type: 'html' },
                            { name: 'is_floor_stock', type: 'bool' },
                            { name: 'created', type: 'number' },
                            { name: 'repairer_status', type: 'string' },
                            { name: 'is_extended_warranty', type: 'bool' },
                            { name: 'is_floor_stock', type: 'bool' },
                            { name: 'is_inhome', type: 'number' },
                            { name: 'is_sandbox_mode', type: 'number' },
                            { name: 'callcentre', type: 'bool' }
                        ],
                    datatype: 'json',
                    data: {
                        params: this.props.params,
                    },
                    //pagenum:1,
                    pagesize: 20,
                    type: 'post',
                    //gotopage:2,
                    root: 'Rows',
                    cache: false,
                    url: process.env.REACT_APP_SOLVUP_API,
                    sort: function () {
                        // update the grid and send a request to the server.
                        letcheck.refs.myGrid.updatebounddata('sort');
                    },
                    filter: function () {
                        // update the grid and send a request to the server.
                        letcheck.refs.myGrid.updatebounddata('filter');
                    },
                    beforeprocessing: function (data) {
                        //console.log(data[0].TotalRows);
                        if (data != null && data.length > 0) {
                            source.totalrecords = data[0].TotalRows;
                        }
                    },
                    pager: function (pagenum, pagesize, oldpagenum) {
                        letcheck.refs.myGrid.updatebounddata('data');
                        // callback called when a page or page size is changed.
                    },
                    sortcolumn: 'id',
                    sortdirection: 'desc'
                };
    
            this.state = {
                dataDetails: [],
                editrow: -1,
                totalNoRecord: 0,
                params: props.params,
                source: source,
                repairerStatus: [],//statusDoc[this.props.params.selectFilter]['status_name'],
                productBrands: [],//statusDoc[this.props.params.selectFilter]['brand_name']
                repairerObj: [],// statusDoc[this.props.params.selectFilter]['rep_obj']
                msgError : '',
                isloading:true
            };
            
            //console.log("constructor "+JSON.stringify(source));
    
        }
    
        componentDidMount() {
            
            this.refs.myGrid.on('filter', (event) => {
                
                let filterGroups = this.refs.myGrid.getfilterinformation();
                var info = "";
                for (var i = 0; i < filterGroups.length; i++) {
                    var filterGroup = filterGroups[i];
                    info += "Filter Column: " + filterGroup.filtercolumn;
                    var filters = filterGroup.filter.getfilters();
                    for (var j = 0; j < filters.length; j++) {
                        info += "\nFilter: ";
                        info += "\nValue: " + filters[j].value;
                        info += "\nCondition: " + filters[j].condition;
                        info += "\nOperator: " + filters[j].operator;
                        info += "\n";
                        
                    }
                }
                
            });
    
            this.refs.myGrid.on('pagechanged', (event) => {
                this.refs.myGrid.updatebounddata('data');
    
            });
    
            this.refs.myGrid.on('bindingcomplete', (event) => {
                
            });
            console.log("load is complete");
        }
    
        componentWillReceiveProps(nextProps) {
            
            this.setState({ repairerStatus: statusDoc[nextProps.params.selectFilter]['status_name'] });
            let temp = this.state.source;
    
            temp.data = {
                params: nextProps.params,
            },
    
            temp.url = process.env.REACT_APP_SOLVUP_API;
    
            this.setState({
                source: temp,
                msgError:''
            });
    
            console.log("state value "+this.state.isloading);
            
    
            this.refs.myGrid.setcolumnproperty('repairer_status', 'filteritems', statusDoc[nextProps.params.selectFilter]['rep_obj']);
            this.refs.myGrid.setcolumnproperty('product_brand', 'filteritems', statusDoc[nextProps.params.selectFilter]['brand_name']);
            this.refs.myGrid.updatebounddata('data');
            this.refs.myGrid.gotopage(0);
           
        }
    
        loadDataAdapter()
        {
            let currentComponent = this;
            return new jqx.dataAdapter(currentComponent.state.source,{ formatData: function (data) { },
            loadComplete: function (data) 
            {
                //this.props.handleDisabled(true)
                //this.setState({isloading:false})
                //console.log(data);
                
            }.bind(this),
            downloadComplete: function (data, status, xhr) {
                console.log("data is loading....." +status);
                currentComponent.props.handleDisabled(true)
                
    
            }.bind(this),
            loadError: function (xhr, status, error)
            { 
                //msgError += xhr.responseText;
                this.setState({msgError:xhr.responseText});
                //console.log(xhr.responseText);
            }.bind(this) 
        
            });
        }
    
        render() {
            
            const hiddenClass = {
                display: 'none',
            };
    
            let repairerSource =
                {
                    datatype: 'array',
                    datafields: [
                        { name: 'label', type: 'string' },
                        { name: 'value', type: 'string' }
                    ],
                    localdata: this.state.repairerObj
                };
    
            let repairerAdapter = new jqx.dataAdapter(repairerSource, {
                autoBind: true
            });
    
            //let letcheck = this;
            let currentComponent = this;
            let dataAdapter = this.loadDataAdapter();
    
            var rendergridrows = function () {
                return dataAdapter.records;
            }
    
            let columns =
                [
                    { text: 'Id', columntype: 'textbox', cellsalign: 'center',width: '8%' , align: 'center', datafield: 'id', filterable: false },
                    { text: 'Customer', columntype: 'textbox',width: '8%', datafield: 'last_name', cellsalign: 'center', align: 'center' },
                    { text: 'Product', datafield: 'item_descriptor',width: '18%', height: '45', cellsformat: 'F2', cellsalign: 'center', align: 'center' },
                    {
                        text: 'Brand', datafield: 'product_brand',width: '8%', filtertype: 'checkedlist', filteritems: currentComponent.state.productBrands, cellsalign: 'center', align: 'center', height: '100'
                    },
                    { text: 'Repairer Name', columntype: 'textbox',width: '8%', datafield: 'repairer_name', cellsalign: 'center', align: 'center' },
                    {
                        text: 'Age', datafield: 'created', filtertype: 'number',width: '10%', cellsalign: 'center', align: 'center', cellsrenderer: function (row, column, value) {
                            return '<div class="jqx-grid-cell-middle-align">' + value + ' days</div>';
                        }
                    },
                    {
                        text: 'Status', datafield: 'repairer_status',filtertype: 'checkedlist', filteritems: new jqx.dataAdapter(repairerSource), cellsalign: 'center', align: 'center',
    
                        createfilterwidget: (column, htmlElement, editor) => {
                            editor.jqxDropDownList({ displayMember: 'label', valueMember: 'value' });
                        }
                    },
                    { text: 'Extended Warranty', datafield: 'is_extended_warranty',filterable: false,hidden: true },
                    { text: 'Floor Stock', datafield: 'is_floor_stock',filterable: false,hidden: true },
                    { text: 'In Home', datafield: 'is_inhome',filterable: false,hidden: true },
                    { text: 'SandBox Mode', datafield: 'is_sandbox_mode',filterable: false,hidden: true },
                    { text: 'Callcentre', datafield: 'callcentre',filterable: false,hidden: true },
                    {
                        text: 'Action', datafield: 'Edit', filterable: false, showfilterrow: false, cellsalign: 'center', align: 'center', columntype: 'button', width: 75, cellsrenderer: function () {
                            return "<i class='fa fa-eye'> </i> <span class='link'> View </span>";
                        }, buttonclick: function (row) {
                            currentComponent.setState({
                                editrow: row
                            });
                            let dataRecord = currentComponent.refs.myGrid.getrowdata(currentComponent.state.editrow);
                            alert(dataRecord.id);
                            // open the popup window when the user clicks a button.
                        }
                    }
                ];
    
            var theme = 'light';
            let getLocalization = () => {
                let localizationobj = {};
                localizationobj.filterselectstring = "Please Choose:";
                return localizationobj;
            }
    
            let listBoxSource =
                [
                    { label: 'Customer', value: 'last_name', checked: true }, 
                    { label: 'Product', value: 'item_descriptor', checked: true },
                    { label: 'Brand', value: 'product_brand', checked: true }, 
                    { label: 'Age', value: 'created', checked: true },
                    { label: 'Status', value: 'repairer_status', checked: true },
                    { label: 'Extended Warranty', value: 'is_extended_warranty', checked: true },
                    { label: 'Floor Stock', value: 'is_floor_stock', checked: true },
                    { label: 'In Home', value: 'is_inhome', checked: true },
                    { label: 'SandBox Mode', value: 'is_sandbox_mode', checked: true },
                    { label: 'Callcentre', value: 'callcentre', checked: true }
                ];
            return (
                <div>
                    
                    {/* <div style={panelStyle}>
                    <JqxDropDownList ref='myDropDownList' style={{ float: 'left' }}
                        width={200} height={25} source={listBoxSource} checkboxes={true}
                        displayMember={'ContactName'} valueMember={'CompanyName'} 
                    />
                    </div> */}
                    {/* { this.state.msgError ?  (<div>There is some error with loading data : {this.state.msgError}</div>) : null } */}
                    <div style={{display: this.state.msgError ? 'block' : 'none' }}>There is some error with loading data : {this.state.msgError}</div>
                    
                    <JqxGrid
                        ref='myGrid'
                        altrows={true}
                        className='myGrid'
                        width='100%'
                        autoheight={true}
                        sortable={true}
                        source={dataAdapter}
                        filterable={true}
                        columns={columns}
                        showfilterrow={true}
                        showsortmenuitems={false}
                        localization={getLocalization()}
                        theme={theme}
                        pageable={true}
                        virtualmode={true}
                        rendergridrows={rendergridrows}
                        autoloadstate={true}
                        autosavestate={true}
                    />
    
                </div>
            )
        }
    }
    

    Thanks


    Hristo
    Participant

    Hello imsonujangra,

    I would like to mention firstly the “bindingcomplete” event which you could use to check when the data binding is completed.
    Yes, I saw it, you are familiar already with this event. You could make one small change to avoid first invoke of this event logic with one flag.
    Because in first load the Grid and the DropDownList maybe is not ready.
    You could try something like that:

    
    let isFirstLoad = true;
    this.refs.myGrid.on('bindingcomplete', (event) => {
    	if(!isFirstLoad) {
    		//your logic
    	} else {
    		isFirstLoad = true;
    	}
    });

    Also, I would like to suggest you look at the article below that could be helpful:
    https://www.jqwidgets.com/jquery-widgets-documentation/documentation/jqxgrid/jquery-grid-extra-http-variables.htm?search=grid
    It is not exactly for the React but you could try to use the principles (‘data’ object and ‘formatData’ callback).

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com


    sonu
    Participant

    Hi Hristo,

    I have tried the way you mention . When i call the parent function in bindingcomplete Event then in parent function will throw warning.

    This is child component.,

    this.refs.myGrid.on('bindingcomplete', (event) => {
       //console.log("complete bindingcomplete");
       this.props.handleDisabled(true)
    });

    In parent component i have handleDisabled function where i’m updating the state after complete the binding.

    handleDisabled(val)
       {
          this.setState({isDisabled:val});
          console.log("ods "+val);
       }

    Warning: Can’t call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in AdvancedSearch (at advanceSearch.js:145)

    So can you please tell me what is the right way to update the parent state when the binding of child component is complete.


    Hristo
    Participant

    Hello imsonujangra,

    You could try directly to use the internal methods.
    I would suggest you bind to the select event (or ‘change’) of the jqxDropDownList and when the event is fired then use this.refs.myDropDownList.disabled(true);
    After that when the bindingcomplete event fired use it again with value false – .destroy(false);.

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com


    sonu
    Participant

    Hi Hristo,

    thanks for the replay. One more thing when i reload the page so the network will call twice the api for the first time. Why it call’s twice is render method call the twice . can u please help me on this.


    Hristo
    Participant

    Hello imsonujangra,

    Is it possible to provide us with one simple example that demonstrates this?

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.