14

I am using react-grid-layout This to enable drag and drop and resizing in my website. SO drag and drop I am able to achieve and storing my layout to local storage is also done.

I am using Local storage to save my layout for better user experience using This example

the thing is what I am trying to do is conditionally give height and width to boxes, like if empName==="steve" than width should be 5 or else it should be 3

So what I did is

const generateLayout = () => {
  const p = data1 || []; //props;
  return p[0].comp_data.map(function (item, i) {
    console.log(item);
    if (item.empName === "steve") {
      return {
        x: (i * 2) % 12,
        y: Math.floor(i / 6),
        w: 2,
        h: 4,
        i: i.toString()
      };
    } else {
      return {
        x: (i * 2) % 12,
        y: Math.floor(i / 6),
        w: 4,
        h: 2,
        i: i.toString()
      };
    }
  });
};

The above approach does not work as required.

Here is the full working code

Edit update

I changed my data, as it was wrong I was looping through p[0]

Now what I did is I created one data for tabs That will show menu ie

    let tabData = [
    {
        tab: 'info',
        id: 1,
    },
    {
        tab: 'info1',
        id: 2,
    },
];

and the other one I have is compData that will have emp status

LIke below

    let data1 = [
    {
        comp_data: [
            {
                empId: 1,
                empName: 'el1',
            },
            {
                empId: 2,
                empName: 'el2',
            },
        ],
    },
    {
        comp_data: [
            {
                empId: 11,
                empName: 'el11',
            },
            {
                empId: 12,
                empName: 'el22',
            },
        ],
    },
];

Important -- actually in my real scenario I am getting all the tabs at one go than I click on one tab get id of that and get compData for that id from backend but here I cannot do it so I put in data1 two objects one for first company and other for other company.

I think this the way for write explanation here

updated code sandbox please check

vivek singh
  • 417
  • 2
  • 12
  • 36
  • Are you expecting the components to always have fixed width? What about the conditional component, should that have a fixed with of 5? Are you expecting to have a single layout without any breakpoints. – AbhishekGowda28 Jun 17 '21 at 10:35
  • @AbhishekGowda28 no fix width it can be resizable , but diff comp will have different widths, that is what I am trying to do. – vivek singh Jun 18 '21 at 05:17

4 Answers4

1

Answering with respect to comment below:

if I just comment local storage it works fine the layout shown UI is per requirement, But as you said to try with state it will not cover my requirement like when I refresh the page it will again go to initial positions. I am using LS to save layouts in that so that when user switches tab or refresh page they should se the same, But this Local storage is the one which is causing issue – 
vivek singh
May 20 at 3:54

As better practice, when you are using the local storage, access the value from local storage and assign it to state at mounting on the component, use it through that state and finally while unmounting the component store the value back in local storage/whenever you are updating the state update the local storage.

In class component: To update while mounting use componentdidMount life cycle method, and more unmounting use componentWillUnmount life cycle method, or you may choose to update local storage every time you update the state value.

In Function component: To update while mounting use const[value, setValue]= useState(loca storage value) life cycle method, and more unmounting use, the return type of the useEffect hook is callback which serves similar to destructor, so you have store the value back to local storage in that callback, or you may choose to update local storage every time you update the state value.

Vishwa
  • 128
  • 4
0

Your if condition in generateLayout is working as it seems because if you add a log as below, You will see that your conditional statement is working `

const layout = generateLayout(); 
console.log(layout);`
Pubudu Jayasanka
  • 1,294
  • 4
  • 18
  • 34
  • but why not ui is displaying accrodingly, i think something is wrong with getFromLs or savetoLS could you please help me out – vivek singh May 20 '21 at 03:29
  • Yes, local storage is not updating correctly – Pubudu Jayasanka May 20 '21 at 03:40
  • Can you get rid of local storage and try to implement it with the state variables? – Pubudu Jayasanka May 20 '21 at 03:49
  • @viveksingh if I have time I would code and check it for you, but I am a bit busy with my office work. I am really sorry for that – Pubudu Jayasanka May 20 '21 at 03:51
  • if I just comment local storage it works fine the layout shown UI is per requirement, But as you said to try with state it will not cover my requirement like when I refresh the page it will again go to initial positions. I am using `LS` to save layouts in that so that when user switches tab or refresh page they should se the same, But this Local storage is the one which is causing issue – vivek singh May 20 '21 at 03:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232619/discussion-between-pubudu-jayasanka-and-vivek-singh). – Pubudu Jayasanka May 20 '21 at 03:59
0

The generateLayout() method is not returning anything and you need to return empId to associate with active menu.

The generateDom() method has to exclude the layouts from non active menu/tab, the keys should be unique so I used the empId for it as well.

check this sandbox https://codesandbox.io/s/elastic-morning-9ufky?file=/src/App.js

const generateDOM = (lo) => {
      const layout = generateLayout();

      return _.map(layout, function (l) {
        const emp = lo.find((item) => {
          return l.i === item.empId;
        });
        if (emp) {
          return (
            <div key={emp.empId} className="bg-success">
              <div>{emp.empName}</div>
            </div>
          );
        } else return <Fragment key={Math.random()} />;
      });
    };

    const generateLayout = () => {
      const p = data1 || []; //props;
      const result = [];
      p.forEach((li) => {
        li.comp_data.forEach(function (item, i) {
          if (item.empName === "Dheeraj") {
            result.push({
              x: (i * 2) % 12,
              y: Math.floor(i / 6),
              w: 6,
              h: 4,
              i: item.empId
            });
          } else {
            result.push({
              x: (i * 2) % 12,
              y: Math.floor(i / 6),
              w: 4,
              h: 2,
              i: item.empId
            });
          }
        });
      });

      return result;
    };
Nader Alfakesh
  • 201
  • 2
  • 5
0

It looks like you first codesandbox example was correct, just only one small mistake, instead of doing p[0] you should do p[active_menu] inside generateLayout()

Demo

Observer
  • 3,506
  • 1
  • 16
  • 32