反应:[标签] - [输入] - [编辑BTN] - [保存BTN-(隐藏)]

发布于 2025-02-03 23:55:02 字数 4058 浏览 4 评论 0原文

如标题所述,我得到了一个简单的CRUD操作,我可以在如何实现的使用效果/USESTATE挂钩方面使用一些帮助。

默认情况下,我将输入设置为禁用,并通过占位符显示上一个值。然后,通过USESTATE/使用效果挂钩更新状态。另外,默认情况下,第二个按钮(保存)设置为隐藏。

目标:

  • 本质上,只是试图为每个编辑输入按钮设置事件侦听器:隐藏编辑按钮,启用输入,请安排保存按钮。

  • 使用单独的(第二)事件侦听器在“保存”按钮上:隐藏保存按钮,请删除编辑按钮,将输入返回禁用的输入,将占位符转到新值并提交值(我有最后一部分的好主意)

jsx:

<label className="col">
  <div className="row">
    <p className="bold nowrap inline-value-title" >Test Name:&nbsp; </p>
    <input 
      id="display-name-change"
      type="text"
      className="form-reset inline-input"
      onChange={(e) => setDisplayName(e.target.value)}
      value={displayName}
      placeholder={user.displayName}
      disabled
    />
    <button type="button" className="inline-button edit-val-btn">
      <FontAwesomeIcon icon={faPenToSquare}  />
    </button>
    <button type="button" className="hidden inline-button save-val-btn">.  
      <FontAwesomeIcon icon={faCircleCheck}  />
    </button>
  </div>
</label>

我的javaScript:(您可能会说它仍然很香草,我认为这是问题)...

const editValueBtns = document.querySelectorAll('.edit-val-btn');
const saveValueBtns = document.querySelectorAll('.save-val-btn');

useEffect(() => {
    editValueBtns.forEach((button) => {
        button.addEventListener('click', (e) => {
            button.classList.add('hidden')
            button.nextSibling.classList.remove('hidden')
            button.parentElement.children[1].removeAttr("disabled") ;
        })
    })

    saveValueBtns.forEach((button) => {
        button.addEventListener('click', (e) => {
            button.classList.add('hidden')
            button.previousSibling.classList.remove('hidden')
            button.parentElement.children[1].addAttr("disabled") ;
        })
    })
}, []);

编辑:显示:显示提交给Firebase/Firestore的输入

const handleSubmit = async (e) => {
    e.preventDefault();
    let selectedFile = document.querySelector('#thumbnailInput')

    // displayname
    if(displayName.length == 0){console.log('No change of name')} 
    else { 
        console.log('change to displayname')
        updateProfile(user, { displayName })
        setDoc(doc(db, 'users', user.uid), { displayName }, { merge: true })

    }

    // phone Number
    if (phoneNo.length == 0){console.log('No change of phone no')}
    else {
        console.log('change to phone')
        updateProfile(user, { phoneNo })
        setDoc(doc(db, 'users', user.uid), { phoneNo }, { merge: true })
    }

    // title
    if (title.length == 0){console.log('No change of title')}
    else {
        console.log('change to title')
        updateProfile(user, { title })
        setDoc(doc(db, 'users', user.uid), { title }, { merge: true })
    }

    // avatar thumbnail
    if(selectedFile.files[0] == undefined){
        console.log('no change to thumbnail')
    } else {
        console.log('change to thumbnail')
        // pass the path in ref to create a StorageReference
        const storageRef = ref(storage,`thumbnails/${user.uid}/${displayName}`) //thumbnail.name

        // upload image, file is a blob here
        await uploadBytes(storageRef, thumbnail);

        const downloadUrl = await getDownloadURL(storageRef);

        // this function returns promise too, add await 
        await updateProfile(user, { photoURL: downloadUrl })

        updateProfile(user, { photoURL: downloadUrl})

        setDoc(doc(db, 'users', user.uid), {
            photoURL: downloadUrl,
        }, { merge: true })
    }

    // clear all form inputs
    const inputs = e.target.querySelectorAll('.form-reset')
    inputs.forEach((input) => {
        input.value=""
    })
}

As the title states, Ive got a simple crud operation I could use some help with the useEffect/useState hook in how to implement.

form input/userdetails

I've got the input set to disabled by default, displaying the previous value via the placeholder. The state is then updated via a useState/useEffect hooks. Also, the second button (save) is set to hidden by default.

Goal:

  • essentially, just trying to setup an event listener for each edit-input button: hide the edit button, enable the input, unhide the save button.

  • with a separate (2nd) event listener on the save button: to hide the save button, unhide the edit button, return the input to disabled, turn the placeholder to the new value, and submit the value(I've got a good idea of the last part)

JSX:

<label className="col">
  <div className="row">
    <p className="bold nowrap inline-value-title" >Test Name:  </p>
    <input 
      id="display-name-change"
      type="text"
      className="form-reset inline-input"
      onChange={(e) => setDisplayName(e.target.value)}
      value={displayName}
      placeholder={user.displayName}
      disabled
    />
    <button type="button" className="inline-button edit-val-btn">
      <FontAwesomeIcon icon={faPenToSquare}  />
    </button>
    <button type="button" className="hidden inline-button save-val-btn">.  
      <FontAwesomeIcon icon={faCircleCheck}  />
    </button>
  </div>
</label>

My Javascript: (as you can probably tell it's still very Vanilla and I think that's the problem)...

const editValueBtns = document.querySelectorAll('.edit-val-btn');
const saveValueBtns = document.querySelectorAll('.save-val-btn');

useEffect(() => {
    editValueBtns.forEach((button) => {
        button.addEventListener('click', (e) => {
            button.classList.add('hidden')
            button.nextSibling.classList.remove('hidden')
            button.parentElement.children[1].removeAttr("disabled") ;
        })
    })

    saveValueBtns.forEach((button) => {
        button.addEventListener('click', (e) => {
            button.classList.add('hidden')
            button.previousSibling.classList.remove('hidden')
            button.parentElement.children[1].addAttr("disabled") ;
        })
    })
}, []);

EDIT: Showing the inputs being submitted to Firebase/Firestore

const handleSubmit = async (e) => {
    e.preventDefault();
    let selectedFile = document.querySelector('#thumbnailInput')

    // displayname
    if(displayName.length == 0){console.log('No change of name')} 
    else { 
        console.log('change to displayname')
        updateProfile(user, { displayName })
        setDoc(doc(db, 'users', user.uid), { displayName }, { merge: true })

    }

    // phone Number
    if (phoneNo.length == 0){console.log('No change of phone no')}
    else {
        console.log('change to phone')
        updateProfile(user, { phoneNo })
        setDoc(doc(db, 'users', user.uid), { phoneNo }, { merge: true })
    }

    // title
    if (title.length == 0){console.log('No change of title')}
    else {
        console.log('change to title')
        updateProfile(user, { title })
        setDoc(doc(db, 'users', user.uid), { title }, { merge: true })
    }

    // avatar thumbnail
    if(selectedFile.files[0] == undefined){
        console.log('no change to thumbnail')
    } else {
        console.log('change to thumbnail')
        // pass the path in ref to create a StorageReference
        const storageRef = ref(storage,`thumbnails/${user.uid}/${displayName}`) //thumbnail.name

        // upload image, file is a blob here
        await uploadBytes(storageRef, thumbnail);

        const downloadUrl = await getDownloadURL(storageRef);

        // this function returns promise too, add await 
        await updateProfile(user, { photoURL: downloadUrl })

        updateProfile(user, { photoURL: downloadUrl})

        setDoc(doc(db, 'users', user.uid), {
            photoURL: downloadUrl,
        }, { merge: true })
    }

    // clear all form inputs
    const inputs = e.target.querySelectorAll('.form-reset')
    inputs.forEach((input) => {
        input.value=""
    })
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妥活 2025-02-10 23:55:02

我看到了您的香草JS方式,并以反应方式提高了您。在React中,您不必使用document.queryselector,preadsibling,parentlement,classList.add,classList.remove,addattr或button.addeventlistener。请参阅

app.jsx

import { Row } from "./components/Row";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <Row placeholder="input 1" />
      <Row placeholder="input 2" />
      <Row placeholder="input 3" />
    </div>
  );
}

row.jsx

import { useState } from "react";

export const Row = ({ defaultValue, placeholder }) => {
  const [value, setValue] = useState(defaultValue);
  const [disabled, setDisabled] = useState(true);

  const handleEditClick = () => {
    setDisabled(false);
  };

  const handleSaveClick = () => {
    setDisabled(true);
    // save logic goes here
  };

  return (
    <label className="col">
      <div className="row">
        <p className="bold nowrap inline-value-title">Test Name:</p>
        <input
          type="text"
          className="form-reset inline-input"
          onChange={(e) => {
            setValue(e.target.value);
          }}
          value={value}
          placeholder={placeholder}
          disabled={disabled}
        />
        {disabled && (
          <button
            type="button"
            onClick={handleEditClick}
            className="inline-button edit-val-btn"
          >
            edit
          </button>
        )}
        {!disabled && (
          <button
            type="button"
            onClick={handleSaveClick}
            className="hidden inline-button save-val-btn"
          >
            save
          </button>
        )}
      </div>
    </label>
  );
};

I see your vanilla js way, and raise you the react way. In react, you shouldn't have to use document.querySelector, previousSibling, parentElement, classList.add, classList.remove, addAttr or button.addEventListener. See solution in CodeSandbox or below:

App.jsx

import { Row } from "./components/Row";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <Row placeholder="input 1" />
      <Row placeholder="input 2" />
      <Row placeholder="input 3" />
    </div>
  );
}

Row.jsx

import { useState } from "react";

export const Row = ({ defaultValue, placeholder }) => {
  const [value, setValue] = useState(defaultValue);
  const [disabled, setDisabled] = useState(true);

  const handleEditClick = () => {
    setDisabled(false);
  };

  const handleSaveClick = () => {
    setDisabled(true);
    // save logic goes here
  };

  return (
    <label className="col">
      <div className="row">
        <p className="bold nowrap inline-value-title">Test Name:</p>
        <input
          type="text"
          className="form-reset inline-input"
          onChange={(e) => {
            setValue(e.target.value);
          }}
          value={value}
          placeholder={placeholder}
          disabled={disabled}
        />
        {disabled && (
          <button
            type="button"
            onClick={handleEditClick}
            className="inline-button edit-val-btn"
          >
            edit
          </button>
        )}
        {!disabled && (
          <button
            type="button"
            onClick={handleSaveClick}
            className="hidden inline-button save-val-btn"
          >
            save
          </button>
        )}
      </div>
    </label>
  );
};
原谅我要高飞 2025-02-10 23:55:02

小调整 ..看来,记录控制台可以使其无法执行它的工作。每次“单击”之后,还从括号中删除了E。 AddAttr和removeAttr也被替换了...其余功能都可以放置在任何一个侦听器中。

编辑:添加了第二个输入,并且似乎仅在第1个输入中起作用。 ..
...是的,我在跟自己说话。

编辑2:它运行良好,直到页面刷新为止...删除了依赖关系阵列,以使其每次工作。我觉得我仍然需要一个清理功能,但是我不能只把活动听众放入一个函数中吗?真的,如果您正在阅读本文,我会喜欢一些经验丰富的意见... :)

useEffect(() => {
    editValueBtns.forEach((button) => {
        button.addEventListener('click', () => {
            button.classList.add('hidden')
            button.nextSibling.classList.remove('hidden')
            button.parentElement.children[1].disabled = false ;
        })
    })

    saveValueBtns.forEach((button) => {
        button.addEventListener('click', () => {
            button.classList.add('hidden')
            button.previousSibling.classList.remove('hidden')
            button.parentElement.children[1].disabled = true ;
        })
    })
});

small tweaks.. it appears that logging the console kept it from doing what it did. also removed the e from the parenthesis after each 'click'. the addAttr and removeAttr also were replaced... the rest of the functionality can be placed in either of the listeners..

EDIT: added a 2nd input and it appears to only work in the 1st input....
...yes I'm talking to myself.

EDIT 2: It worked fine until the page refreshed... removed the dependency array for it to work every time. I feel like i still need a cleanup function, but I can't just place the event listeners into a function can i? Really, if you're reading this i would love some more experienced input... :)

useEffect(() => {
    editValueBtns.forEach((button) => {
        button.addEventListener('click', () => {
            button.classList.add('hidden')
            button.nextSibling.classList.remove('hidden')
            button.parentElement.children[1].disabled = false ;
        })
    })

    saveValueBtns.forEach((button) => {
        button.addEventListener('click', () => {
            button.classList.add('hidden')
            button.previousSibling.classList.remove('hidden')
            button.parentElement.children[1].disabled = true ;
        })
    })
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文