reactjsdevextremedevextreme-react

is there any way so that I could able to move my location and comment fields as shown in the figure


sample Image that I want to achiveSo the problem is I'm using devextreme components for my react applications. In building this special page I got struct with a special case in devextreme UI case. I have a row containing headers two lines of headers. first line is the fixed line of headerson top of table containing shed, storagetype,assignedbags,capacity, maxbags, lead,bagsper layer. the second line containing rendering header below to the shed and storagetype, they are location and comment. So when I press the button to add the location should add the new row. I tryed to perform the same thing but I'm getting the single line row. Please help me

import React, { useState,useEffect } from "react";
import apis from "../api-constants";
import './temporarystack.scss';
import DataGrid, { Column } from "devextreme-react/data-grid";
import useGetAPI from "../getAPIS";
import { Button, SelectBox } from "devextreme-react";
import { formatMessage } from "devextreme/localization";

export default function TemporaryStack ({tokenDetails,operation,isTempUsed,temporaryStacksJSON}) {
    
    const [showTable, setShowTable] = useState(false);
    const [listData, setListData] = useState([]);
    const [shedOptions, setShedOptions] = useState(null);
    const [threshold,setThreshold]=useState({})
    const storageTypeOptions=[
      {id:1,name:'Gang Way'}, 
      {id:2,name:'Alley Way'}, 
      {id:3,name:'Road Side'}, 
      {id:4,name:'Plinth'}, 
      {id:5,name:'Others'}
    ]
  
  
    useEffect(()=>{
      
      async function Dataapi(){
        const responceforshed=await useGetAPI(apis.GET_GODOWN_UNITS(operation))
        const responceforthreshold=await useGetAPI(apis.GET_BAGWEIGHT_THRESHOLD_MAXIMUXBAGCAPACITY)
        setShedOptions(responceforshed.data)
        setThreshold(responceforthreshold.data)
      }
  
      if(showTable===true){
        Dataapi()
      }
      
    },[operation,tokenDetails,showTable])
    useEffect(()=>{
      temporaryStacksJSON(listData)
    },[listData])
    
    // removing data when Temporary stack is unchecked and initialization state
    const handleCheckboxChange = (e) => {
      const isChecked = e.target.checked;
      setShowTable(isChecked);
      isTempUsed(isChecked)
      if (!isChecked) {
        setListData([])
      }
    };
    
    // adding new row to the temporary stack
    const addRow = () => {
      const newItem = {
        shed: shedOptions && shedOptions.length > 0 ? shedOptions[0]?.value : '', 
        storageType: storageTypeOptions.length > 0 ? storageTypeOptions[0].name : '',
        assignedBags: '',
        capacity: '',
        maxBags: '',
        lead: '',
        bagsPerLayer: '',
        locationDescription: '',
        comment: '',
      };
      setListData((prevList) => [...prevList, newItem]);
  
    };
  
  
    // to delete a temporary stack
    const deleteRow = (index) => {
      const updatedList = [...listData];
      updatedList.splice(index, 1);
      setListData(updatedList);
    };
  
    // rendering the table or state change for data
    const renderTable = () => {
      if (!showTable) return null;
  
      return (
        <>
          <DataGrid dataSource={listData} showBorders={true} style={{padding:0,margin:0}} className="table">
              {/* column for selection of shed */}
            <Column 
            width={25}
            cellRender={record=>{
              return(record.rowIndex+1)
            }}/>
            <Column
              caption={formatMessage("Shed")}
              width={100}
              minWidth={80}
              cellRender={(record) => (
                <SelectBox
                  width={80}
                  dataSource={shedOptions}
                  displayExpr={'value'}
                  valueExpr={'value'}
                  onValueChange={e=>{
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].shed = e;
                    setListData(updatedList);
                  }}
                  value={record.data.shed}
                  defaultValue={record.data.shed}
                  />
              )}
            />
            {/* selection of storage type */}
            <Column
              width={100}
              minWidth={80}
              caption={formatMessage('StorageType')}
              cellRender={(record) => (
                <SelectBox
                  dataSource={storageTypeOptions}
                  displayExpr="name"
                  valueExpr="name"
                  onValueChanged={e=>{
                    const updatedList = [...listData];
                        updatedList[record.rowIndex].storageType = e.value;
                        setListData(updatedList);
                  }}
                  value={record.data.storageType}
                  defaultValue={record.data.storageType}
                  />
              )}
            />
  
            <Column dataField="assignedBags" caption={formatMessage("AssignedBagInTemp")} 
            cellRender={(record) => (

                <input
                  type="number"
                  defaultValue={record.data.assignedBags}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].assignedBags=parseInt(e.target.value)
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
            <Column dataField="capacity" caption={formatMessage('Capacity')} 
            cellRender={(record) => (
                <input
                  type="number"
                  defaultValue={record.data.capacity}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].capacity=parseInt(e.target.value)
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
            <Column dataField="maxBags" caption={formatMessage('MaxBags')} 
            cellRender={(record) => (
                <input
                  type="number"
                  defaultValue={record.data.maxBags}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].maxBags=parseInt(e.target.value)
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
            <Column dataField="lead" caption={formatMessage("Lead")} 
            cellRender={(record) => (
                <input
                  type="number"
                  defaultValue={record.data.lead}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].lead=parseInt(e.target.value)
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
            <Column dataField="bagsPerLayer" caption={formatMessage('BagsPerLayer')} 
            cellRender={(record) => (
                <input
                  type="number"
                  defaultValue={record.data.bagsPerLayer}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].bagsPerLayer=parseInt(e.target.value)
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
            <Column dataField="locationDescription" caption={formatMessage('LocationDescription')} 
            cellRender={(record) => (
                <textarea
                  defaultValue={record.data.locationDescription}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].locationDescription=e.target.value
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
            <Column dataField="comment" caption={formatMessage('Commentl')} 
            cellRender={(record) => (
                <textarea
                  defaultValue={record.data.comment}
                  onBlur={(e) => { 
                    const updatedList = [...listData];
                    updatedList[record.rowIndex].comment=e.target.value
                    setListData(updatedList);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault();
                    }
                  }}
                />
            )}/>
  
            {/*  column to delete the row  */}
            <Column 
              width={50}
              cellRender={(cellData) => (
                  <Button 
                    icon="close" 
                    onClick={() => deleteRow(cellData.rowIndex)}
                    style={{borderRadius:'10%',backgroundColor:'rgba(249, 172, 156, 0.44)'}}
                    />
              )}
            />

          </DataGrid>
           <Button 
            icon="plus" 
            onClick={addRow}
            style={{borderRadius:'10%',backgroundColor:'#c7ecc7',padding:0}}
            />
        </>
      );
    };
  
    return (
      <>
        <label>
          <input type="checkbox" onChange={(e) => handleCheckboxChange(e)} />
          {formatMessage('TemporaryStack')}
        </label>
        {renderTable()}
      </>
    );
  };

I try to shift the column but haven't succeed


Solution

  • In DevExtreme, DataRow is a class representing a row in a data source, typically used within a data grid or similar components. When you refer to "datarowrender," you might be talking about customizing how these rows are rendered in a DevExtreme data grid.

    In DevExtreme, you can customize the rendering of data rows using templates or through event handlers like onRowPrepared. Here's how you can customize the rendering of data rows:

    Using Templates: DevExtreme provides templates that allow you to customize the appearance of various parts of the grid, including data rows. You can define a template for the data rows and specify the HTML and/or Angular/React/Vue components to render within each row. Here's an example of how you might define a data row template in DevExtreme:
    
    <DataGrid
      dataSource={dataSource}
      onRowPrepared={handleRowPrepared}
    >
      <RowTemplate>
        {(rowData, rowIndex) => (
          <div className={rowIndex % 2 === 0 ? 'even-row' : 'odd-row'}>
            {/* Custom rendering for each data row */}
            <span>{rowData.name}</span>
            <span>{rowData.age}</span>
          </div>
        )}
      </RowTemplate>
    </DataGrid>
    

    Using Event Handlers: You can also use event handlers like onRowPrepared to customize the rendering of data rows dynamically. This event is triggered for each row before it is rendered, allowing you to modify its appearance based on data or other conditions. Here's an example:

      dataSource={dataSource}
      onRowPrepared={handleRowPrepared}
    />
    

    and the function code is:

      if (e.rowType === 'data') {
        // Customize row appearance based on data
        if (e.data.age < 18) {
          e.rowElement.classList.add('minor-row');
        } else {
          e.rowElement.classList.add('adult-row');
        }
      }
    }
    

    caution:Since datarowrender is a type of function which render every time if there is a small change and cancels out if is used