Érték visszaadás a táblázat celláiba
2022-08-02T16:34:22+02:00
2022-08-09T20:14:45+02:00
2022-08-09T20:30:29+02:00
M-anos
Egy korábbi kérdésben fejlesztett kódot (Dinamikus táblázat Javascripttel) tovább fejlesztenék, viszont egy kicsit eladtam.

Javascript segítségével egy táblázathoz új sorokat tudok hozzá adni. A sorok celláiba űrlap elemek kerülnek bele (beviteli mező, checkbox, legördülő lista).

Az űrlap elemeket két függvény segítségével oldanám meg (createFormElem és selectCreateElem). Ezeket a függvényeket hívom be oda, ahol vizsgálom a létrehozandó űrlap elemeket.

if(emp.elementTyp == "text" || emp.elementTyp == "checkbox") { const formInputElem = createFormElem(emp.elementTyp, emp.id, emp.name, emp.css, emp.placeholder); cell.append(formInputElem); } if(emp.elementTyp == "select") { const formSelectElem = selectCreateElem(emp.url, emp.id, emp.name); cell.append(formSelectElem); }
Amikor createFormElem függvény szépen vissza is adja az input típusokat a cellákba, viszont a selectCreateElem függvény sajnos nem adja vissza a cellákba a létrehozott legördülő listákat.

Mikor új sort adok hozzá a táblázathoz, és a selectCreateElem függvény lefut, akkor a következő hibaüzeneteket kapom:

Ha így szeretném hozzáadni a sor cellájához a generált legördülő listát cell.append(formSelectElem); akkor undefined értéket kapok a cellékban.

Ha pedig így szeretném a cellához hozzáadni a generált legördülő listát cell.appendChild(formSelectElem); akkor pedig "Uncaught TypeError: Node.appendChild: Argument 1 is not an object." hibaüzenetet kapom.


A fontos Javascript kódrészlet:

let formElements = [ { elementTyp: 'text', id: 'oneID', name: 'oneName', css: 'form-control', placeholder: 'onePLC' }, { elementTyp: 'select', url: 'https://api.frankfurter.app/latest', id: 'twoID', name: 'twoName' }, { elementTyp: 'select', url: 'https://api.frankfurter.app/latest', id: 'threeID', name: 'threeName' }, { elementTyp: 'text', id: 'FourID', name: 'fourName', css: 'form-control', placeholder: 'fourPLC' } ]; function addNewRow(tableIDS,formElements) { let listTable = document.getElementById(tableIDS); let row = listTable.tBodies[0].insertRow(); formElements.forEach(emp => { let cell = row.insertCell(); if(emp.elementTyp == "text" || emp.elementTyp == "checkbox") { const formInputElem = createFormElem(emp.elementTyp, emp.id, emp.name, emp.css, emp.placeholder); cell.append(formInputElem); } if(emp.elementTyp == "select") { const formSelectElem = selectCreateElem(emp.url, emp.id, emp.name); cell.append(formSelectElem); } row.appendChild(cell); }); let cell = row.insertCell(); let addBtn = document.createElement('input'); addBtn.setAttribute('type', 'button'); addBtn.setAttribute('value', '-'); addBtn.setAttribute('onClick', 'deleteRow("'+tableIDS+'",this)'); addBtn.setAttribute('class', 'btn btn-danger btn-sm'); cell.appendChild(addBtn); row.appendChild(cell); } function createFormElem(type, id, name, css, placeholder) { let inputText = document.createElement('input'); inputText.setAttribute('type', type); inputText.setAttribute('id', id); inputText.setAttribute('name', name); inputText.setAttribute('class', css); inputText.setAttribute('placeholder', placeholder); return inputText; } function selectCreateElem(url, id, name) { fetch(url) .then((response) => response.json()) .then((data) => { let selectEL = document.createElement("select"); selectEL.setAttribute('name', name); selectEL.setAttribute('class', "form-select rounded-0"); selectEL.setAttribute('id', id); let currencies = Object.entries(data.rates).forEach(([code, value]) => { let optionEl = document.createElement("option"); optionEl.value = code; optionEl.text = value; selectEL.appendChild(optionEl); }); return selectEL; }) .catch((err) => console.log(err)); }
Mutasd a teljes hozzászólást!
Én így írnám át a selectCreateElem függvényt:

async function selectCreateElem(url, id, name) { try { const response = await fetch(url); const data = await response.json(); const selectEL = document.createElement("select"); selectEL.setAttribute('name', name); selectEL.setAttribute('class', "form-select rounded-0"); selectEL.setAttribute('id', id); for (const [code, value] of Object.entries(data.rates)) { const optionEl = document.createElement("option"); optionEl.value = code; optionEl.text = value; selectEL.appendChild(optionEl); }); return selectEL; } catch (err) { console.log(err)); } }
Ezt innentől async függvényből lehet meghívni "await selectCreateElem(...)" formában, vagy ha await nélkül hívod, akkor a kapott Promise objektumot kell a szokásos módon kezelni (hívsz rá then()-t, catch()-et, akármit).

De egyébként ha azt mondod hogy az await tiszta de a Promise nem, akkor valószínűleg az await-et sem érted teljesen. Az async és await Promise objektumok kényelmes gyártásáról és fogyasztásáról szól lényegében, csak a szintaxis elrejti előled magukat az objektumokat.
Mutasd a teljes hozzászólást!

  • Ha lenne egy forintom minden kérdező után, akik nem értették hogy az AJAX / fetch hívások aszinkron futnak le... akkor lenne vagy 50 forintom

    Amikor hívsz egy fetch()-et, akkor a böngésző elindít egy HTTP kérést, de nem várja meg a választ. A különböző then(), catch() és egyéb callback-ek majd akkor futnak le, ha megérkezett a válasz (vagy soha, ha az oldalt előbb bezárják mint ahogy a válasz megérkezne). A callbackben már mindegy mit adsz vissza, a fetch()-et meghívó függvény addigra már rég visszatért, mégpedig undefined értékkel, mert hogy nem volt benne return utasítás.

    Nézz utána az async/await témakörnek. Azon ugyan nem segítenek, hogy a HTTP válaszokat meg kell várni, de legalább a kódodat nem kell teleszórni egy rakás callback függvénnyel, amik a választ lekezelik.

    Mondjuk az nem annyira egészséges, ha te DOM manipuláció közben küldesz HTTP kéréseket. A válasz megérkezéséig a felhasználó egy félkész DOM fát lát, amivel interakcióba is tud lépni. Barátságosabb lenne két fázisban: először elküldöd a szükséges kéréseket (közben a felhasználónak mutathatsz homokórát vagy pörgettyűt vagy ami éppen most divatos), aztán ha megvan minden adat, akkor egy menetben felfrissíted a DOM fát. Ráadásul a HTTP kérések futhatnak párhuzamosan, a Promise.all() függvény a barátod.
    Mutasd a teljes hozzászólást!
  • Szia. Async/await az tiszta, ezt a függvényt meg tudom oldani, viszont a Promise az nekem még újdonság. Esetleg egy egyszerű példával el tudnád magyarázni, hogy is tudom a két dolgot egybe rakni, hogy szintaktikailag akkor helyes legyen? Tiszta sor, hogy a soronként megadandó űrlap elemeket, máshogy kell, hogy bejárjam (tehát a fetch-es lekéréseket külön kell kezelnem, hogy ne akkor generàodjanak le a lista elemek mikor új sort adok hozzá.).
    Mutasd a teljes hozzászólást!
  • Én így írnám át a selectCreateElem függvényt:

    async function selectCreateElem(url, id, name) { try { const response = await fetch(url); const data = await response.json(); const selectEL = document.createElement("select"); selectEL.setAttribute('name', name); selectEL.setAttribute('class', "form-select rounded-0"); selectEL.setAttribute('id', id); for (const [code, value] of Object.entries(data.rates)) { const optionEl = document.createElement("option"); optionEl.value = code; optionEl.text = value; selectEL.appendChild(optionEl); }); return selectEL; } catch (err) { console.log(err)); } }
    Ezt innentől async függvényből lehet meghívni "await selectCreateElem(...)" formában, vagy ha await nélkül hívod, akkor a kapott Promise objektumot kell a szokásos módon kezelni (hívsz rá then()-t, catch()-et, akármit).

    De egyébként ha azt mondod hogy az await tiszta de a Promise nem, akkor valószínűleg az await-et sem érted teljesen. Az async és await Promise objektumok kényelmes gyártásáról és fogyasztásáról szól lényegében, csak a szintaxis elrejti előled magukat az objektumokat.
    Mutasd a teljes hozzászólást!
  • Módosítottam a kódomat, az általad megírt függvénnyel.

    A probléma továbbra is fennáll ahol meg hívom a függvényt:

    if(emp.elementTyp == "select") { const formSelectElem = selectCreateElem(emp.url, emp.id, emp.name); cell.appendChild(formSelectElem); } row.appendChild(cell); });
    Ha a cell.appendChild(formSelectElem); esetén a hiba: (Uncaught TypeError: Node.appendChild: Argument 1 does not implement interface Node.).

    Viszont ha lecserélem az appendChild-et innerHTML-re - cell.innerHTML = formSelectElem;  akkor a consolba kiírva visszatérnek az értékek (kép mellékleve).

    Az érdekelne, hogy az appendChild esetén miért nem tér vissza az érték az innerHTML-el szemben.
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • Amikor azt írtam, hogy

    Ezt innentől async függvényből lehet meghívni "await selectCreateElem(...)" formában, vagy ha await nélkül hívod, akkor a kapott Promise objektumot kell a szokásos módon kezelni (hívsz rá then()-t, catch()-et, akármit).

    akkor nem arra gondoltam, hogy ne nyúlj semmihez a hívóban és minden jó lesz. Tényleg meg kéne értened a Promise témakört (ideértve az async és await működését), mert ha csak vaktában nyomkodsz dolgokat azzal nem fogsz boldogulni. Ha ez megvan, már azt sem lesz gond megérteni, hogy a konzol a Promise példány jelenlegi állapotát mutatja, nem azt az állapotot, amiben a log hívás idején volt.
    Mutasd a teljes hozzászólást!
  • Igen, vannak még hiányosságok, nem is tagadom. Most tanulom a javascripttet. Eddig jquery-t használgattam, csak közben változott a helyzet, és nem szeretném azt használni, hanem inkább a modern javascript-tel szeretnék foglalkozni.
    Mutasd a teljes hozzászólást!
abcd