jQuery dodawanie elementu tak by był widoczny jako obiekt

0

Witam,
mam problem związany z dodawaniem elementów input do formularza, ale tak by go rozpoznawał.

Chodzi o to że pobieram metodą html() kawałek kodu i dodaję go w inne miejsce poprzez .append(). Problem polega na tym, że jak robię $('form :input').each() to pobiera tylko elementy, które były utworzone na początku, a omija te które zostały stworzone dynamicznie w trakcie wypełniania formularza.

Co mam z tym zrobić? Czy muszę zamienić to na obiekt, a może jakoś powiedzieć jQuery o tym, że były robione zmiany.

Oczywiście cały kod jest w $(function() { ... });

Bardzo proszę o pomoc.

0

Zapewne gubisz się z kolejnością wykonywania jakichś zdarzeń, które lecą jednocześnie i tego each robisz przed append. Pokaż kod.

0

prawdopodobnie przypisujesz $('form :input') do zmiennej PRZED dodaniem nowych pól. W przeciwieństwie do żywych list utworzonych na przykład przez getElementsByTagName('input'), lista elementów jQuery nie jest aktualizowana przy zmianach drzewa DOM.

W jQuery możesz jedynie dodawać zdarzenia do nowo utworzonych elementów metodą .on - tak przypisane zdarzenia automatycznie dodadzą się do wszystkich elementów istniejących teraz i tych utworzonych w przyszłości. Jeżeli w swoim .each przypisujesz właśnie zdarzenia to .on będzie rozwiązaniem problemu

BTW - zamiast używać .html() do pobrania tekstowej reprezentacji kodu, profesjonalniej będzie sklonować obiekt metodą .clone()

kopiowany.clone().appendTo(element);

lub:

element.append(kopiowany.clone());

zamiast:

element.append(kopiowany.html());
0

Dzięki za odpowiedź. Tak sądziłem, że chodzi o "przekazanie informacji o aktualizacji". Jeżeli chodzi o .clone() to nie używam bo po skopiowaniu kawałku kodu potrzebuję go trochę poprzerabiać - działam na stringach. Dodatkowo muszę pobrać tylko zawartość elementu.

A właśnie, czy można zrobić tak by po skopiowaniu elementu odwoływać się do jego atrybutów? Przykład:

<input type="text" name="item[]" elem-id="1" />

I teraz kopiuje to (już olejmy w jaki sposób się odwołuje bo to akurat nie ma tutaj znaczenia) i chcę dokonać zmiany elem-id na 2. Czy da się jakoś to zrobić by nie bawić się w operacje na stringach?
Patrzyłem na konwertowanie stringa na obiekt jQuery, ale to nic nie dało.

0

jak już sklonujesz obiekt, to wystarczy dać:

element.attr('elem-id', 2);

Dodatkowo muszę pobrać tylko zawartość elementu.

to użyj element.contents().clone()

przykładowo, kod klonujący elementy formularza zwiększając elem-id o 10:

$('form')
  .contents().clone()
    .each(function() {
      $(this).attr('data-elem-id', ~~$(this).attr('data-elem-id') + 10);
    })
  .appendTo($('form'));

(prawdopodobnie zamiast 10 będziesz chciał podstawić najwyższe data-elem-id)
tak jak napisał kolega niżej powinieneś użyć data-elem-id zamiast elem-id

0

zamiast elem-id, daj data-elem-id --- poprawnie w HTML5 ;)

0

Dziękuję za wszelkie podpowiedzi. Muszę poczytać o ~~ bo nawet nie wiedziałem, że coś takiego istnieje (tym bardziej nie wiem jak dokładnie działa).

Dodatkowo fajnie, że będę mógł używać .clone() bo to zwraca jQuery Object a nie String :D

Jeszcze muszę powrócić do poprzedniego zagadnienia. Chodzi o to, że mam formularz, który sprawdza poprawność danych po zjechaniu z pola tekstowego (blur). Wygląda to tak:
Kod html (a dokładnie szablon, bo PHP jest w innych plikach - mam swój parser nie Smarty), a poniżej niego kod jQuery (po zmianie):

$(function()
{

validate_data();

// Po nacinięciu "Dodaj" kopiuję zawartoć pól
$('input.copy').on('click', function(){	
	// Zliczam iloć elementów input i dodaję 1
	var nr = $('td[data-id="'+$(this).attr('data-event')+'"] input').length + 1;
	// Skracam zapis
	var elem = $('td[data-id="'+$(this).attr('data-event')+'"] span.copy');
	// Kopiuję element zmieniajšc atrybut data-elem-id na kolejny
	var copy = elem.contents().clone().attr('data-elem-id', nr).val('');
	// Dodaję kopię
	$('td[data-id="'+$(this).attr('data-event')+'"]').append(copy);
});

});

A oto część kodu w validate_data():

$('form :input').blur(function(){
   // ... tutaj kod sprawdzający
});

Mimo to nie działa nadal... Sprawdzałem czy kolejność funkcji ma wpływ i nie ma. Coś czuję, że do elementów powinienem się odwoływać wpisując przed nimi form.

0

validate_data() wykonujesz na samym początku - tam przypisujesz funkcję do zdarzenia blur istniejących wtedy elementów
tak jak pisałem wcześniej jak chcesz przypisać zdarzenie do przyszłych elementów to użyj .on
linijkę

$('form :input').blur(function(){

zamień na:

$('form :input').on('blur', function(){

nie ma co czytać o ~~
~ to po prostu negacja bitowa - z 00101011 robi 11010100
~~ to podwójna negacja bitowa więc liczba powraca do tej samej postaci
myk polega na tym że po zrobieniu negacji bitowej na stringu zamienia się on na liczbę, nawet jeśli był typu undefined

0

Fajna metoda z tym ~~. Co do .on('blur') to już też robiłem - sorki, że nie napisałem. Mimo to nie widzi tego ...

Zrobiłem 2 rzeczy:

  1. W .on('blur', function(){ ... } dodałem alert('blur');
  2. Po dodaniu nowego pola input robię $('form :input').length;

I teraz dla pkt.1 nie wyświetla alertu blur dla inputów dodanych dynamicznie, ale natomiast po dodaniu każdego nowego inputu pkt.2 wyświetla informację o zwiększeniu się ilości tych pól.

Wszędzie w kodzie pozmieniałem na .on('event')

Dodatkowo validate_data() przeniosłem na sam koniec, a na początku dodałem jeszcze jedno zdarzenie:

$('form :input').on('keypress', function(e){
	alert('key');
});

I oczywiście dla dodanych pól nadal to nie działa... Zastanawia mnie czy może sposób dodawania nowych pól jest w jakiś sposób nieodpowiedni?

//edit:
Chyba znalazłem rozwiązanie. Zamiast:

$('form :input').on('event' function{...});

Powinno być:

$('form').on('event', input', function{...});

Dla zdarzenia keypress działa - zastosuje w innych miejscach też i napiszę jaki efekt :D

//edit
Działa wszystko jak należy. Dzięki wielkie za duuuuuużą lekcję jQuery.

Pozdrawiam.

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