Ajax przekazanie wartości zmiennej do thymeleaf w Spring boot

0

Cześć,
mam modal, w którym chciałbym wyświetlać produkty z koszyka. Produkty dodaję do koszyka przy pomocy ajaxa, po kliknięciu w button jest uruchamiana funkcja w ajaxie dodajDoKoszyka().
Mam tutaj zrobioną pętlę, która dodaje produkt do koszyka, a następnie pobiera listę i wyświetla ją w modalu. Jednak chciałbym to zrobić w inny sposób. Zamiast dodawać w ajaxie paragrafy z nazwą produktu chciałbym przekazać całą listę do modala, gdzie znajdowałby się div z th:each i tutaj byłaby zmienna powiedzmy **${listaProduktów} **, przy pomocy której mógłbym wyświetlać sobie co tylko chcę z tej listy. Czy jest możliwe przekazanie całej listy z ajaxa do zmiennej w thymeleafie? Bardzo proszę o pomoc.

Modal:

<div class="modal fade" id="dodanoDoKoszykaModal" tabindex="-1">
                            <div class="modal-dialog">
                              <div class="modal-content">
                                <div class="modal-header">
                                  <h5 class="modal-title" id="dodanoDoKoszykaModalTitle">Dodano do koszyka</h5>
                                  <button type="button" class="close" data-dismiss="modal">
                                  </button>
                                </div>
                                <div class="modal-body"  id="dodanoDoKoszykaModalBody">
                                    <!-- W ten sposób chciałbym wyświetlać listę produktów z koszyka -->
                                    <div class="listaaaa" th:each="produkt : ${listaProduktow}">
                                        <p th:text="${produkt.nazwaProduktu}"></p>
                                    </div>
                                    
                                    <!-- Tak robię to teraz, w ajaxie dodaję do tego diva paragraf -->
                                    <div id="listaProduktow">
                                    </div>
                                </div>
                                <div class="modal-footer">
                                  <button type="button" class="btn btn-success" data-dismiss="modal">OK</button>
                                </div>
                              </div>
                            </div>
                          </div>

Funkcja dodawania produktu do koszyka w ajaxie:

function dodajDoKoszyka(nazwaProduktu)
{
    url = "/test" + nazwaProduktu;
    
    $.ajax({
        type: "POST",
        url: url,
        beforeSend: function(xhr){
            xhr.setRequestHeader(csrfHeaderName, csrfValue);
        }
    }).done(function(response)
    {
        $("#dodanoDoKoszykaModalTitle").text("Koszyk");
        $.each(response, function(index, value){
            $("#listaProduktow").append($("<p>").text(value.nazwaProduktu));
        });

        $("#dodanoDoKoszykaModal").modal();
    }).fail(function()
    {
        $("#dodanoDoKoszykaModalTitle").text("Error");
        $("#dodanoDoKoszykaModalBody").text("Źle");
        $("#dodanoDoKoszykaModal").modal();
    });
}
0

Rozumiesz ze thymeleaf to server-side-template? I renderuje się przy odpowiedzi z serwera? Jak twój koszyk jest client-side w JS to nijak nie da się to nic zaczarować.
Zrób to moze jak człowiek:

  • dodanie do koszyka wysyła request do serwera z produktami
  • serwer trzyma sobie stan koszyka
  • front wysyła ajaxa z pytaniem o koszyk i dostaje jsona z koszykiem
0

Czyli jak rozumiem nie da się zrobić tego w taki sposób jak chciałem?
No ja teraz robię to tak, że kliknięcie buttona wywołuje funkcję w ajaxie, ponieważ nie mogłem wywołać metody z kontrolera. Żeby to zrobić musiałbym zrobić requesta, jednak nie chcę żeby po dodaniu do koszyka produktu przenosiło mnie na jakąś inną podstronę, chcę tylko żeby wyświetlił się modal z listą aktualnych produktów znajdujących się w koszyku.

Tylko jeśli z frontu wywołam funkcję z ajaxa, która ma pobrać listę produktów z koszyka to ja znowu tego nie przekażę do fronta, czy się mylę?

0
annonymouzinho napisał(a):

jednak nie chcę żeby po dodaniu do koszyka produktu przenosiło mnie na jakąś inną podstronę, chcę tylko żeby wyświetlił się modal z listą aktualnych produktów znajdujących się w koszyku.

A czemu ma Cię przenosić na inna podstronę? Wiesz co to jest Http Request?

Tylko jeśli z frontu wywołam funkcję z ajaxa, która ma pobrać listę produktów z koszyka to ja znowu tego nie przekażę do fronta, czy się mylę?

????????

Wysyłasz na backend request, dostajesz produkty obecnie znajdujące się w koszyku i je wyświetlasz. Jaki problem?

ps Kto Cię tak skrzywdził podpowiadając, że powinieneś uczyć sie javy webowej korzystając z Thymeleafa i Ajaxa?

0

Poniżej znajduje się kawałek kodu z podstrony produktów. Wyświetlane są tutaj wszystkie produkty znajdujące się w bazie danych.

<div class="listaProdoktowContainer" th:each="produkt : ${listaProduktowNaStronie}">
                        <div class="col-sm-12">
                        <ul>
                            <li>
                                <button class="zdjecie" th:disabled="${produkt.dostepnosc_produktu}==false"
                                        th:onclick="'window.location.href = \'' + @{/{nazwaProduktu}(nazwaProduktu=${produkt.nazwaProduktu})} + '\''">
                                    <img th:src="@{${produkt.sciezka_zdjecia}}" width="180" height="130"/>
                                </button>
                            </li>
                            <li><span id="nazwaAktualnegoProduktu" th:text="${produkt.nazwaProduktu}"></span></li>
                            <li><span class="cena" th:text="${#numbers.formatDecimal(produkt.cena_brutto_produktu, 0, 2)} + ' zł'"></span></li>
                            <li>
                                <span th:switch="${produkt.dostepnosc_produktu}">
                                    <p class="produktDostepny" th:case="true">&#x2714 Produkt dostępny</p>
                                    <p class="produktNiedostepny" th:case="false">&#10006 Produkt niedostępny</p>
                                </span>
                            </li>
                            <!-- Tutaj wywołuje metodę z kontrolera -->
                            <li><button type="button" class="btn btn-warning dodajDoKoszyka" th:id="${produkt.nazwaProduktu}" th:disabled="${produkt.dostepnosc_produktu}==false" 
                                       th:onclick="'window.location.href = \'' + @{/test/{nazwaProduktu}(nazwaProduktu=${produkt.nazwaProduktu})} + '\''"
                                       >Dodaj do koszyka</button>
                            </li>
                            <li>
                                <div sec:authorize="hasRole('ROLE_ADMIN')">
                                <button type="button" class="btn btn-primary" id="edytujProdukt" th:onclick="'window.location.href = \'' + @{/edytuj_produkt/{id}(id=${produkt.idProduktu})} + '\''">Edytuj</button>
                                <button type="button" class="btn btn-danger" id="usunProdukt">Usuń</button>
                                </div>
                            </li>
                        </ul>
                        </div>
                    </div>

A tutaj jest kod metody z kontrolera, która dodaje produkt do listy, a następnie zwraca wszystkie produkty znajdujące się w koszyku. Jednak tak jak pisałem wyżej, zostaje przekierowany na tą podstronę, a tego nie chcę, chciałbym pozostać na stronie z produktami i żeby po kliknięciu buttona pojawił się modal, gdzie przy pomocy th:each przypisałbym do zmiennej właśnie listę produktów z koszyka i sobie to fajnie wyświetlił.

@RequestMapping(value = "/test/{nazwaProduktu}", method = RequestMethod.POST)
    public List<Produkt> dodajProduktDoKoszyka(@PathVariable(name = "nazwaProduktu") String nazwaProduktu)
    {
        Optional<Produkt> produkt = produktRepo.findByNazwaProduktu(nazwaProduktu);
        produktService.dodajProduktDoKoszyka(produkt.get());

        List<Produkt> produkty_w_koszyku = produktService.pobierzProduktyZKoszyka();
        return produkty_w_koszyku;
    }
1
annonymouzinho napisał(a):

Poniżej znajduje się kawałek kodu z podstrony produktów. Wyświetlane są tutaj wszystkie produkty znajdujące się w bazie danych.
A jeśli chodzi o jave webową, to jest to moja pierwsza styczność z nią, wybrałem sobie taki projekt, z thymeleafem wydaje mi się wszystko prostsze i łatwiejsze.

Z thymeleafem nic nie jest prostsze. Powtórzę to 20 raz. Po co pchać się na początku przygody z webówką w widoki? Najpierw ogarnij swoje API RESTowe aby było poprawnie napisane, a dopiero potem dodawaj do tego front krok po kroku.

Chociażby w Twoim controllerze:

@RequestMapping(value = "/test/{nazwaProduktu}", method = RequestMethod.POST)
    public List<Produkt> dodajProduktDoKoszyka(@PathVariable(name = "nazwaProduktu") String nazwaProduktu)
    {
        Optional<Produkt> produkt = produktRepo.findByNazwaProduktu(nazwaProduktu);
        produktService.dodajProduktDoKoszyka(produkt.get());

        List<Produkt> produkty_w_koszyku = produktService.pobierzProduktyZKoszyka();
        return produkty_w_koszyku;
    }

Po co Ci ten Optional skoro potem i tak używasz get() bez żadnego sprawdzania.
Poza tym cała ta 'logika' nie powinna być w controllerze.

0

No rozumiem, widocznie źle wybrałem ale niestety teraz już tego nie mogę zmienić muszę skończyć to tak jak zacząłem.
Optional jest, ponieważ tak to w repozytorium zrobiłem żeby w innym miejscu sprawdzić czy dany produkt istnieje, a nie chciałem robić drugiej takiej samej metody tylko bez optionala to tak już zostawiłem.
A wracając do mojego pytania, to czy mogę w jakiś sposób zrobić to tak żeby mnie nie przekierowywało na tą podstronę? I przekazać tą listę do modala?
Bo jeśli nie to chyba sobie odpuszczę wyświetlanie koszyka po dodaniu produktu do koszyka i wyświetlę po prostu informację, że produkt został dodany.

0

Myśle że twój problem polega na tym, ze nie wiesz ze jest coś takiego jak @RestController który zwraca "dane" a nie robi żadnych przekierowań na inną stronę ;) Jak używasz @Controller i zwracasz jakieś ModelAndView to niestety wszystko odbywa się na zasadzie request-response i przeładowuje stronę.

1
  1. Nie pisz po polsku.
  2. Popraw swoje API.
  3. Jakbyś wrzucił to na GH to byłoby prościej.
  4. Wywal tego TL'a.
  5. A jeśli, aż tak bardzo się przy nim upierasz to przeanalizuj co zwracasz z tej metody. Jak już bawisz się w TLa i widoki to powinieneś zwracać te właśnie widoki, a nie listę produktów. Coś w stylu: definiujesz sobie szablon koszyka i po każdej operacji dodaj/usuń zwracasz z API jego model.

NIe powinienem tego wklejać, skoro odradzam Ci TL'a, ale tutaj jest to w miarę OK napisane: https://github.com/reljicd/spring-boot-shopping-cart

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