且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在全局标签内创建动态元素

更新时间:2023-02-04 21:08:37

Issues You are Facing

  1. If length of data is less than four I am providing a plus button to create on more tab (give it default name), but I am not getting any idea how can I create the new one.

Here you want to get a new name, i.e. a form on the page with a text input, random generate name, use a prompt as I did below. Call setData and use a functional state update to spread existing data into a new array and append a new data object.

const addNewTab = () => {
  /**
   * window.prompt is just a quick way to request input from user. 
   */
  const name = window.prompt('Enter Name');

  /**
   * logic to generate next id, but could be anything really
   */
  const id = generateId();

  if (name) {
    setData((data) => [...data, new Data(id, name)]);
  }
};

  1. When I click on side button to create one dive inside tab, and I go to other tab and come back again I want that created div should not gets deleted.

A couple things going on here. First, you defined data1 in the function body so it is reset every render cycle. Keep the data in state, data can be provided as initial state. Second, you need to add the created elements. Do this by updating state.

Move data1 out of the component and define local component state initialized with data (update all references in render from data to data).

const [data, setData] = useState(data1);

Similar approach as adding a new tab, get the new data name and title. Here we call setData and again use a functional state update, but this time we'll map the existing state to a new array. When the array index matches the active tab index this is the data object we need to updated. Spread its myData into a new array and append the new data object. If index isn't a match then just return the element.

const Create_element = () => {
  /**
   * window.prompt is just a quick way to request input from user. 
   */
  const data_name = window.prompt('Enter Data Name');
  const data_title = window.prompt('Enter Data Title');

  if (data_name && data_title) {
    setData(data => data.map((el, i) => i === active_menu ? {
      ...el,
      myData: [...el.myData, { data_name, data_title }],
    } : el))
  }
};

  1. Suppose I have 3 tabs (data) so when page loads the first tab data I want to show, but it is not showing up I need to click there only it is showing up.

Issue here is caused by keeping a separate nestedData state object that is only ever updated when a tab is clicked. When a new element is added to the active tab's myData array nestedData isn't updated. Solution here is to simply render the nested data directly in the UI.

Update the tab's onClick handler to simply set the active menu (index).

onClick={() => setactive_menu(index)}

Render the myData directly from the new data state.

data[active_menu].myData.map((li, index) => (...

  1. If the data is null then I can create up to 4 tabs this also I a=want some Idea to do it.

Conditionally rendering the ADD button will control this.

{data.length < 4 && <button onClick={addNewTab}>ADD</button>}

Full Code

import React, { useState } from "react";
import "./styles.css";

import RightBar from "./Right_option";
import NEsted from "./Nested";

import "bootstrap/dist/css/bootstrap.min.css";

/**
 * https://***.com/questions/63814645/how-to-create-dynamic-elements-inside-global-tabs
 */

const data1 = [
  {
    id: 1,
    name: "Maxi",
    myData: [
      {
        data_name: "div1",
        data_title: "div1 tittle"
      },
      {
        data_name: "div1",
        data_title: "div tittle"
      }
    ]
  },
  {
    id: 2,
    name: "Phill",
    myData: [
      {
        data_name: "div21",
        data_title: "div21 tittle"
      }
    ]
  }
];

/**
 * Data object constructor
 * @param {number} id new data object id
 * @param {string} name new data object name
 * @example
 * new Data(1, 'Bill')
 */
const Data = (id, name) => ({ id, name, myData: [] });

/**
 * Id generator hook
 * @param {number} [seed=0] initial id generator value
 * @returns {function}
 */
const useIdGenerator = (seed = 0) => {
  function* genId(seed = 0) {
    let i = seed;
    while (true) yield i++;
  }

  const generator = genId(seed);

  return () => generator.next().value;
};

export default function App() {
  const generateId = useIdGenerator(5);

  const [data, setData] = useState(data1);
  const [active_menu, setactive_menu] = useState(0);

  const Create_element = () => {
    /**
     * window.prompt is just a quick way to request input from user.
     */
    const data_name = window.prompt("Enter Data Name");
    const data_title = window.prompt("Enter Data Title");

    if (data_name && data_title) {
      setData((data) =>
        data.map((el, i) =>
          i === active_menu
            ? {
                ...el,
                myData: [...el.myData, { data_name, data_title }]
              }
            : el
        )
      );
    }
  };

  const addNewTab = () => {
    /**
     * window.prompt is just a quick way to request input from user.
     */
    const name = window.prompt("Enter Name");

    if (name) {
      setData((data) => [...data, new Data(generateId(), name)]);
    }
  };

  return (
    <div className="App row">
      {data.map((li, index) => (
        <div className="col-4 col-sm-4 col-md-3 col-lg-3 col-xl-3" key={index}>
          <div
            className={
              index === active_menu
                ? "row dashboard_single_cont_active"
                : "row dashboard_single_cont"
            }
            onClick={() => setactive_menu(index)}
          >
            <div className="dashboard_name col-10 col-sm-10 col-md-9 col-lg-10 col-xl-10">
              {li.name}
            </div>
            <div
              className={
                active_menu === index
                  ? "dashboard_option_active col-2 col-sm-2 col-md-3 col-lg-2 col-xl-2"
                  : "dashboard_option col-2 col-sm-2 col-md-3 col-lg-2 col-xl-2"
              }
              align="center"
            ></div>
          </div>
        </div>
      ))}

      {data.length < 4 && <button onClick={addNewTab}>ADD</button>}

      <div className="col-11 col-sm-11 col-md-11 col-lg-11 col-xl-11">
        <div className="row">
          {data[active_menu].myData.map((li, index) => (
            <div
              key={index}
              className="col-11 col-sm-11 col-md-8 col-lg-6 col-xl-6"
            >
              <NEsted data={li} />
              <br></br>
            </div>
          ))}
        </div>
      </div>
      <RightBar Create_element={Create_element} />
    </div>
  );
}