div input wykorzystany w dwóch miejscach, a event listener

0

Witam,
Mam pytanie, a zarazem problem, może opiszę po krótce.

Apka w jsie. Po nacisnięciu btn__add wyświetla mi diva z inputami, oraz przyciskiem save i cancel. Użytkownik wpisuje nazwe, i zapisuje. Jest validacja, tworzy się task w obiekcie i jako element LI w UL.

W globalscope, w klasie APP, mam listener na btn__save i btn__cancel ( save tworzy obiekt, cancel wychodzi i samyka inputa poprzez remove ()).

I teraz pytanie.

Implementuje opcję edycji tasku. Po naciśnięciu elementu li z btn__edit, ponownie wyświetla mi się mój div z inputami i wypełnionymi danymi do edycji.
Natomiast btn__save i btn__cancel dalej mają przypisane funkcje do zapisu i stworzenia nowego obiektu.

Moje pytanie. Jak rozwiązać ten problem które rozwiązanie będzie najlepsze, dodam że div input zmienia swoje miejsce w doomTree i zastępuje przy edycji element li.

Przy add_new jest to, UL > LI, LI, LI | DIV_INPUT
PRZY task_edit jest to, UL > LI, DIV_INPUT, LI LI ,,,,,,, <= li elm zastąpiony div inputem.

  • rozwiązanie 1: usunąć global scope, i badać poprzez container-listener --- E. target - parentNode. Czyli raz parent jest Ulem ( w przypadku edycji ), w przypadku dodawania nowego jest jeszcze wyżej.

-rozwiązanie 2. EventTarget.removeEventListener() - słyszałem o czymś takim ale nie wiem czy działa.

-rozwiązanie 3. Zrobić osobnego diva z klasą edit i do niego osobne listenery.

Jakieś inne rozwiązanie ?

Chodzi o czysty JS, wiem że w reacie nie byłoby problemu.
Prosiłbym o wskazówkę.

0

Proponuję zrobić obiekt stanu (dodawanie, edycja) i dla niego zaimplementować w zależności od wyboru:

  • procedurę odczytu stanu dla listenera albo
  • procedurę dynamicznego (prze)budowania diva z odpowiednimi listenerami (usunięcie, dodanie) albo
  • procedurę przełączania gotowych divów

Według mnie najlepsze rozwiązanie to 2. lub 3. w zależności od skomplikowania zmian w kodzie strony.

0

@overcq: Dziękuję za odpowiedź. Projekt który robię jest treningowy w ramach nauki i chyba źle do niego podszedłem. Tzn dodanie "stejtów" będzie wymagało przeróbki wszystkiego.
Sam temat natomiast ciekawy i fajne wprowadzenie przed frameworkami, będę się musiał na tym skupić.

Czy takie źródło nauki jest ok ? https://css-tricks.com/build-a-state-management-system-with-vanilla-javascript/
W repo jest fajny ( przynajmniej tak mi się wydaje ), przykład factory, do tworzenia komponentów, i zarządzanie stanami.

Wydaje mi się to dość skomplikowane. Zwłaszcza że moduły dopiero liznąłem, i też muszę je zacząć wprowadzać do ćwiczeń

0

Czytałem trochę na ten temat, który jest dość rozległy. Zdaję już sobie sprawę że moje rozwiązanie jest trochę słabe, ale wiem dlaczego. Mam też pewne podejrzenia jak powinna wyglądać sprawa z rozwiązaniem, ale ciężko mi to napisać. Będę musiał chyba na mniejszym przykładzie tego spróbować.

Używając mojego diva który wyświetla okno inputa dla tworzenia nowego obiektu, i jego edycji.
Czy powinno to wyglądać tak.

naciskam np: btn_show_input <-- do tworzenia nowego obiektu, i w state sobie zmieniam żeby wiedzieć że kliknąłem : btn_show_input ( czyli dodawanie nowego )

naciskam np: btn_edit <-- na elemencie li <-- do tworzenia edycji obiektu, i w state sobie zmieniam żeby wiedzieć że kliknąłem : btn_edit( czyli edycje istniejacego obiektu )

Na podstawie state renderuje ten input ? np poprzez innerHTML - tworzę go jako nowy input i dodaje do niego listenery ?

W przypadku 1 - listenery z funkcjami do dodania nowego
W przypadku 2 - listenery z funkcjami do edycji istniejącego ?

rozumiem że state ma robić za taką flagę która rozpoznaje którą opcję wybrałem ?

Zrobiłem na sztywno w spaghetti drugi input do edycji. Zmieniłem mu nazwę klasy. Ale musialbym zmienić wszyskie klasy także na butonach, bo listenery musiałbym ustawiać na querySelectorALL -< bo jest więcej niż jeden.

Czy taki utworzony obiekt z dodanymi listenerami, poprzez metodę dynamicznego tworzenia nasłuchuje cały czas ? Rozumiem że ma to służyć temu ze jak zmienie state i wyrenderuje input to moje listenery też się zmienią. I będa indywidualne zależny od wartości state ?

0

Ok, przeglądnąłem link.
Wbrew opisowi na podanej stronie podany tam obiekt stanu nie jest w pełni wykorzystany. Z tego, co przeczytałem, to zaprezentowane tam demo wykorzystuje programowanie zdarzeniowe. Widać to wyraźnie w implementacji klas, które rozszerzają Component, np. w klasie List. Przy wystąpieniu zdarzenia stateChange jest wywoływana funkcja render, która wstawia kod html na stronę.
W tym, co proponowałem w pierwszej odpowiedzi, główne miejsce zajmowałby obiekt stanu i wymienione w tym demo mutations. Natomiast stany byłyby konkretnie zdefiniowane dla aplikacji, a nie zmieniane ot tak sobie. Czyli byłaby logika zmian stanów w aplikacji.
Nie wiem, czy w sensie powyższego wprowadzenie obsługi stanów wymagałoby zmiany struktury Twojej aplikacji, ponieważ nie musisz do tego wprowadzać programowania zdarzeniowego, jak w podanym demo.
Natomiast zdefiniowanie procedur zmiany stanu pozwoli uniknąć chaosu w programie i nie dopuści do powstania wewnętrznych zależności (takich jak sprawdzanie rodzica inputa).
W międzyczasie widzę kolejną odpowiedź, więc się odniosę.
W tym konkretnym przypadku stany można nazwać po prostu widokami. Czyli masz dodawanie nowego albo edycja istniejącego. Natomiast pozostaje decyzja, co do tego, jak wiele kodu html jest gotowego, by nie dodawać go przez innerHTML (najlepiej wszystko obiektowo).

  • Przypadek pierwszy podany w poprzedniej odpowiedzi: procedura odczytu stanu dla listenera.
    Nie zmieniasz listenerów tylko wewnątrz nich sprawdzasz stan (widok), by wiedziały, jak się zachować.
  • Przypadek drugi: pro­ce­du­ra dy­na­mi­cz­ne­go (prze)bu­do­wa­nia di­va z od­po­wie­d­ni­mi lis­te­ne­ra­mi.
    Robisz coś, jak w podanym przez ciebie linku do demo aplikacji, ale bez programowania zdarzeniowego, tylko przez wywołanie procedury przełączenia widoku.
  • Przypadek trzeci: pro­ce­du­ra prze­łą­cza­nia go­to­wych di­vów.
    Masz dwa pełne fragmenty html i przełączasz ich widoczność (z CSS display). Wtedy są zawsze przypisane odrębne listenery.
0

@overcq: Dziękuję bardzo za odpowiedź, jeszcze raz - nie sądziłem że się ktoś zainteresuje. Przeczytałem twoją informacje, spróbuję to napisać. Ewentualnie jeszcze o coś zapytam gdy polegnę.

Natomiast zdefiniowanie procedur zmiany stanu pozwoli uniknąć chaosu w programie i nie dopuści do powstania wewnętrznych zależności (takich jak sprawdzanie rodzica inputa).

To zdanie mnie bardzo zainteresowało.

To mój pierwszy prosty projekt, coś ala taskLista z elementem liczenia czasu nauki. Gdy użytkownik wykonana sesje nauki na zadany task, task aktualizauje właściwości obiektu. Liczy ile ktoś na danym tasku spędził czasu itp. Całość napisana w dużym chaosie, miała za zdanie przećwiczyć podstawy, operacje na obiektach, i tablicach. Im dalej w las tym do aplikacje zacząłem dodawać różne rzeczy. Chaos i tak się wkradł bo pewnie struktura aplikacji jest masakryczna. Ponad 400-500 lini samego js'a w jednym pliku. Zacząłem pisać jak nie znałem modułów.

Pisze o tym by oddać punkt w którym jestem i stan :) Większość rzeczy o których piszesz jest dla mnie nowa, ale ciekawi mnie bardzo to co napisałeś. Nie wiem skąd czerpać wiedzę o strukturze aplikacji, i planowaniu.

Odnośnie przypadku trzeciego czyli: "Przypadek trzeci: pro­ce­du­ra prze­łą­cza­nia go­to­wych di­vów.
Masz dwa pełne fragmenty html i przełączasz ich widoczność (z CSS display). Wtedy są zawsze przypisane odrębne listenery."

Wiem że przełączanie widku typu opacity 0 / display none jest wydajniejsze od remove oraz insertBefore na przykład. Nie wiem co mnie podkusiło że z tego zrezygnowałem.

Prawdopodobnie to że: W przypadku gdy input był poniżej UL czyli w przypadku wprowadzania nowego tasku --> nie miałem problemu: manipulowałem display / opacity.
Edycję chciałem zrobić nie poprzez otwarcie tego okna w tym samym miejscu ale poprzez kliknięcie na element LI który chce edytować:

  • w miejsce elementu li wstawiałem input ( ten sam, z wypełnionymi danymi) poprzez replaceChild
    coś takiego:
    - let parent = clickedElement.parentNode; parent.replaceChild(taskeditTask, clickedElement);

gdzie clickedElement - to element li pobrany przez :
const clickedElement = e.target.closest('.task__item');

Piszę o tym bo nie wiem czy w ogóle to dobrze zrobiłem i jak powinno się takie rzeczy rozwiązywać by uzyskać taki efekt. Ale już mi do głowy przychodzi pomysł, że elementu: clickedElement mógłbym nie usuwać a ukrywać a przed niego wstawiać okno inputa do Edycji.

Spróbuję przypadku trzeciego.

0

przerobiłem state od deski do deski, zrobiłem proste mvc i wszystko się rozjaśniło. Dzięki za podpowiedzi

1 użytkowników online, w tym zalogowanych: 0, gości: 1