• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[GELÖST] jQuery addClass() auf dynamischen Content funktioniert nicht

Broco

New member
categories.png
Hallo zusammen!

Bastle gerade eine Seite, auf der in einer Box Kategorien verwaltet werden sollen (siehe Bildanhang).
Die schon vorhandenen Kategorien werden via AJAX und PHP aus einer mySQL-Datenbank geladen. Die Funktion dazu sieht so aus (ich weiß nicht genau, ob ich CODE oder PHP verwenden soll, aber bei PHP funktioniert wenigstens das Highlighting, also nehmts mir nicht übel, falls das falsch sein sollte):

PHP:
function GetCategories()
{
  var url = './ajax/training_management_data.php';
  $('#training_management_categories_items').html('<ul style="list-style: none; margin-left:0px; margin-top:0px; padding:0px;" id="training_management_categories_items_ul"></ul>');
  $('#training_management_categories_items_ul').append(' \
    <li class="training_management_categories_list"> \
      <a href="" class="training_management_categories_list_a" id="training_management_categories_list_a_all">Alle</a> \
    </li> \
  ');
  $.ajax({
    url: url,
    type: "POST",
    data: {
      action: 'get_categories',
    },
    dataType: 'JSON',
    success: function (data) {
      $.each(data, function(index, data) {
        $('#training_management_categories_items_ul').append(' \
          <li class="training_management_categories_list"> \
            <a href="" class="training_management_categories_list_a" data-id="'+data.id+'" id="training_management_categories_list_a_'+data.id+'">'+data.name+'</a> \
          </li> \
        ');		
      });
    }
  });
}

Das funktioniert auch alles.
Ich habe eine Klasse ".categories_selected", die für die angeklickten Items verwendet wird, auch das funktioniert:
PHP:
$('#training_management_categories_items').on('click', '.training_management_categories_list_a', function (e) {
		e.preventDefault();
		categoryid = $(this).attr('id');
		selectedcategoryid = $(this).attr('data-id');
		selectedcategoryname = $(this).text();
		$("#training_management_categories_items>ul>li>a").removeClass('categories_selected');
		$(this).addClass('categories_selected');
		//alert("ID: "+selectedcategoryid);
		if (categoryid == training_management_categories_list_a_all) {
			categorySelected = 0;
		}
		else {
			categorySelected = 1;
		}
		CheckIfCategoryChecked();
	});

Jetzt ist es aber so, dass ich, nachdem ich eine Kategorie erstellt oder bearbeitet habe, diese auch automatisch auswählen will. Ich habe also folgende Funktion geschrieben:
PHP:
function selectEditedCategory(catid) {
  categoryid = 'training_management_categories_list_a_' + catid.toString();
  $("#training_management_categories_items>ul>li>a").removeClass('categories_selected');
  $('#'+categoryid).addClass('categories_selected');
  console.log(categoryid);
}

Ich rufe also zum Beispiel selectEditedCategory(selectedcategoryid) auf, wobei selectedcategoryid natürlich die ID des Eintrags aus der Datenbank und damit auch die ID des Elements ist (siehe Funktion GetCategories() oben).
Zum Testen logge ich das Ganze sogar mit und das Log sagt:
training_management_categories_list_a_80
Also soweit alles vollkommen gut. Allerdings funktioniert es nicht, die Klasse wird nicht hinzugefügt.
Nutze ich
PHP:
$('#'+categoryid).trigger('click');
Funktioniert es auch nicht (der Click event löst das Hinzufügen der Klasse korrekt aus).
Mache ich das hier:
PHP:
document.getElementById(categoryid).click();
Gibt mir die Konsole den Fehler aus, dass document.getElementById(categoryid) null wäre, allerdings ist categoryid völlig korrekt laut Konsole.

Habe noch mal mit Firebug drüber geschaut und Firebug zeigt den Quellcode (ich gebe jetzt mal einen Beispiellink) nach dem AJAX-Call so an:
HTML:
<a id="training_management_categories_list_a_86" class="training_management_categories_list_a" data-id="86" href="">ads</a>
Also ist die id des Links vollkommen richtig gesetzt.

Ich bin ratlos.
Es ist nicht so, dass ich die Funktion unbedingt brauche (wobei es schon gut wäre), es geht mir hier mehr ums Verständnis, weil ich absolut am Ende mit meinem Latein bin.

Ich danke schonmal im Voraus für jede Hilfe bei diesem Rätsel.

Gruß
Broco

P.S.: Nicht über das Attribut "data-id" wundern, darin wird nur die ID gespeichert, also ohne den Text davor als reine Zahl. So brauche ich nicht nachher noch den Text zu strippen. Ist HTML5-konform ;-)
 
Zuletzt bearbeitet von einem Moderator:
Ganz spontan fällt mir dazu etwas ein, was ich vor etlicher Zeit mal hatte. Und zwar hab ich da auch ein Klick in einem Formular per JS ausgelöst und danach ließ sich das Formular nicht mehr senden. Egal ob per Ajax oder "normal". In der Konsole stand sinngemäß, dass das aus Sicherheitsgründen nicht erlaubt ist. Aber ich finde das nicht mehr. Könnte das hier auch sowas sein? Die Konsole hast du immer im Blick?

Achso, noch was: Manchmal kann man sich helfen, punktuell für die Dauer der Fehlersuche mal die ursprüngliche JS Syntax anstatt jQuery zu verwenden. Grund: Bei jQuery wird nur selten ein Fehler in der Konsole angezeigt, bei "normalem" JS hingegen schon.
 
Zuletzt bearbeitet:
Von welchem Typ ist denn categoryid? Mach doch mal ein console.log(typeof categoryid);
 
Hallo zusammen,

mikdoe schrieb:
Die Konsole hast du immer im Blick?
Ja, keine Fehler, ich hab auch schon die Variable auf der Konsole ausgeben lassen und sie zeigt die ID des Elements korrekt an, z.b. training_management_categories_list_a_84, also wird der String korrekt zusammengesetzt und auch Firebug zeigt den HTML-Quelltext korrekt an.

s4ty schrieb:
Von welchem Typ ist denn categoryid? Mach doch mal ein console.log(typeof categoryid);
Ist String, wurde ja auch so festgelegt: categoryid = 'training_management_categories_list_a_' + catid.toString();
catid ist die ID als Int, die per JSON übermittelt wurde.

hesst schrieb:
wo und wann rufst du selectEditedCategory auf?
Wenn man auf "Neu" klickt, gibt es einen Dialog (startCategoryNewDialog) und wenn man dort auf Speichern klickt, wird der AJAX-Call aufgerufen (submitNewCategory). Die dazugehörigen Funktionen sind diese:

PHP:
function startCategoryNewDialog() {
  $('#new_category_dialog').dialog({
    width: 250,
    height: "auto",
    show: {
      effect: "fade",
      duration: 300,
    },
    hide: {
      effect: "fade",
      duration: 300
    },
    draggable: false,
    open: function() {
      popupbg(true);
      $('#new_category_dialog_error').hide();
    },
    close: function() {
      popupbg(false);
      
    },
    buttons:{
      //Submit with click
      Anlegen:function(){
        submitNewCategory();
      },
      Abbrechen:function(){
        $('#new_category_dialog').dialog('close');
      }
    }
  });
}

function submitNewCategory() {
  var url = './ajax/training_management_data.php';
  if ($('#new_category_dialog_name').val().length < 2) {
    $('#new_category_dialog_error').html('<b>Fehler:</b><br>Der Name einer Kategorie muss mindestens 2 Zeichen lang sein.')
    $('#new_category_dialog_error').show( "blind" ,300);
  }
  else {
    $('#new_category_dialog_error').hide();
    $.ajax({
      url: url,
      type: "POST",
      data: {
        action: 'new_category',
        category_name: $('#new_category_dialog_name').val()
      },
      dataType: 'JSON',
      success: function (data) {
        if (data[0].operation == 'success') {
          selectedcategoryid = data[0].id;
          GetCategories();
          $('#new_category_dialog_name').val('');
          selectEditedCategory(selectedcategoryid); //HIER WIRD DIE FUNKTION AUFGERUFEN
          $('#new_category_dialog').dialog('close');
        }
        else if (data == 'error-name_present') {
          $('#new_category_dialog_error').html('<b>Fehler:</b><br>Kategorie mit gleichem Namen bereits vorhanden.')
          $('#new_category_dialog_error').show( "blind" ,300);
        }
        else {
          $('#new_category_dialog_error').html('<b>Fehler:</b><br>Fehler beim Anlegen der Kategorie.')
          $('#new_category_dialog_error').show( "blind" ,300);
        }
      }
    });
  }
}

Ich glaube aber, es liegt am zeitlichen Ablauf, ich verstehe nur nicht ganz, warum. Ich habe es jetzt hinbekommen, indem ich den Funktionsaufruf in den Close-Bereich des Dialogs packe.

Ich würde nur gerne verstehen, warum das nicht in dem success-Bereich des AJAX-Calls geklappt hat. Schließlich wird ja erst GetCategories() aufgerufen und dann die select-Funktion. Heißt für mich, dass die Funktionen gleichzeitig aufgerufen werden und zum Zeitpunkt des Aufrufs von selectEditedCategory() GetCategories() noch nicht mit dem Hinzufügen der Inhalte fertig war.

Kann sein, dass ich etwas betriebsblind bin gerade. Also prinzipiell ist das Problem gelöst, nur würde ich gerne das "Warum" verstehen.

Vielen Dank schonmal an alle und viele Grüße

Broco
 
selectEditedCategory() müsste im Callback von GetCategories() stehen. Da GetCategories() asyncron ausgeführt wird, ist selectEditedCategory() ehr fertig. Deswegen liefert dein Selektor keine Treffer, da das Element dazu noch nicht erzeugt wurde.

Man hätte das auch einfach mit console.log($('#'+categoryid).length); sehen können, da length in dem Fall 0 gewesen sein müsste.
 
Zuletzt bearbeitet:
selectEditedCategory() müsste im Callback von GetCategories() stehen. Da GetCategories() asyncron ausgeführt wird, ist selectEditedCategory() ehr fertig.

Ja, du hast natürlich Recht, ich bin blöde. Allerdings kann ich die Funktion nicht in den Callback von GetCategories setzen, weil GetCategories auch beim Laden der Seite und nach dem Löschen eines Elements aufgerufen wird, um die Liste zu aktualisieren.

Es funktioniert allerdings Problemlos, wenn ich diesen Teil in die Close-Funktion des Dialogs fürs Editieren und Neu anlegen einfüge.
PHP:
if (typeof selectedcategoryid != 'undefined' && selectedcategoryid != 0) {
        selectEditedCategory(selectedcategoryid);
      }

Vielen Dank für eure Hilfe!

P.S.: Ist mir jetzt ein bisschen peinlich, aber wie setze ich das Thema auf "Gelöst"?

Edit:
s4ty schrieb:
Man hätte das auch einfach mit console.log($('#'+categoryid).length); sehen können, da length in dem Fall 0 gewesen sein müsste.
Ja, das stimmt, ich hatte nur console.log(categoryid); gemacht, was den richtigen Wert angezeigt hat und das hatte mich verwirrt.
 
Zuletzt bearbeitet:
Zurück
Oben