Jquery data attribuut werkt niet zoals verwacht

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Endreaw nvt

Endreaw nvt

15/06/2017 21:43:29
Quote Anchor link
Hallo,

Ik heb een formulier gemaakt, waarin dynamisch velden worden toegevoegd, met erachter een knop om de regel weer te verwijderen. Dit doe ik doofmiddel van data attribute in HTML waarbij ik een regelnummer toevoeg.

Nu werkt het dynamisch toevoegen van een regel, en ik kan een al bestaande regel verwijderen maar zodra ik een nieuwe regel toevoeg kan ik die regel niet meer verwijderen

De jQuery die ik gebruik voor het toevoegen van extra velden en het verwijderen ervan, hierbij is de variabel fieldcounter een waarde waarmee ik begin met invoegen van extra velden
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
$('.removeProduct').click(function(e) {
        // Determinate if we need to add extra fields or not
        var productRule = ($(this).data('remove'));

        console.log("Clicked removeProduct");
        console.log(productRule);

        $('#modalRemoveButton').click(function(e) {
            console.log("Called removeProduct");
            console.log("ProductRule 1 " + productRule);
            if($('.productName:visible').length == 1) {
                $('#removeRuleError').modal('show');

                console.log("Show error modal");
            } else {
                console.log("ProductRule 2 " + productRule);
                $("input[name='removed["+ productRule + "]'").val('1');
                $('#productLine' + productRule).hide('slow');

                console.log("Removed product");
            }
        });

    });

    /**************************************************************************
    *     dd extra fields to the product pages.
    *
    *      @ Attribute(s)         fields
    *    @ Usage             Set fields to true, to add extra fields
    *     
    ***************************************************************************/
    $('#addField').click(function(e) {
        var addExtraFields = $(this).data('fields');
        var fields = '<div class="row" id="productLine'+ fieldStart +'"><div class="col-md-4"><input class="form-control productName" placeholder="Productnaam" name="productName['+ fieldStart +']" type="text"></div><div class="col-md-1"><input class="form-control" placeholder="Aantal" name="amount['+ fieldStart +']" type="text"></div><div class="col-md-1" style="width: 9.5%"><input class="form-control price" placeholder="Prijs" name="price['+ fieldStart +']" type="text"></div>';

        // If there are extra fields required add them
        if(addExtraFields) {
            fields += '<div class="col-md-1"><input class="form-control" name="removed['+ fieldStart +']" type="text" value="0"></div><div class="col-md-1"><a data-toggle="modal" data-target="#removeRule"><div  id="'+ fieldStart +'" class="removeProduct btn btn-green glyphicon glyphicon-trash trashcan"></div></a></div>';
        }

        // Close row
        fields += '</div>';

        // Append the extra fields
        $('#extraFields').append(fields);
        $('#'+ fieldStart).attr("data-remove", fieldStart);

        // Update the readonly state of the price textbox
        changeDisabledStatePrice();

        fieldStart++;
    });


De HTML:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="row" id="productLine1">
    <div class="col-md-4">
        <input class="form-control productName" name="productName[1]" type="text">
    </div>
    <div class="col-md-1">
        <input class="form-control" name="amount[1]" type="text">
    </div>
    <div class="col-md-1" style="width: 9.5%;">
        <input class="form-control" name="price[1]" type="text">
    </div>
    <div class="col-md-1">
        <input class="form-control" name="removed[1]" type="text">
    </div>

    <div class="col-md-1">
        <a data-toggle="modal" data-target="#removeRule">
            <div  class="removeProduct btn btn-green glyphicon glyphicon-trash trashcan" data-remove="1"></div>
        </a>
    </div>
</div>
Gewijzigd op 15/06/2017 22:11:41 door Endreaw nvt
 
PHP hulp

PHP hulp

26/01/2020 11:54:12
 
Jacco Engel

Jacco Engel

16/06/2017 07:40:41
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function addRemoveEvent() {
    $('.removeProduct').unbind("click");
    $('.removeProduct').click(function(e) {
        // Determinate if we need to add extra fields or not
        var productRule = ($(this).data('remove'));

        console.log("Clicked removeProduct");
        console.log(productRule);

        $('#modalRemoveButton').click(function(e) {
            console.log("Called removeProduct");
            console.log("ProductRule 1 " + productRule);
            if($('.productName:visible').length == 1) {
                $('#removeRuleError').modal('show');

                console.log("Show error modal");
            } else {
                console.log("ProductRule 2 " + productRule);
                $("input[name='removed["+ productRule + "]'").val('1');
                $('#productLine' + productRule).hide('slow');

                console.log("Removed product");
            }
        });

    });
}

addRemoveEvent();
    /**************************************************************************
    *     dd extra fields to the product pages.
    *
    *      @ Attribute(s)         fields
    *    @ Usage             Set fields to true, to add extra fields
    *    
    ***************************************************************************/
    $('#addField').click(function(e) {
        var addExtraFields = $(this).data('fields');
        var fields = '<div class="row" id="productLine'+ fieldStart +'"><div class="col-md-4"><input class="form-control productName" placeholder="Productnaam" name="productName['+ fieldStart +']" type="text"></div><div class="col-md-1"><input class="form-control" placeholder="Aantal" name="amount['+ fieldStart +']" type="text"></div><div class="col-md-1" style="width: 9.5%"><input class="form-control price" placeholder="Prijs" name="price['+ fieldStart +']" type="text"></div>';

        // If there are extra fields required add them
        if(addExtraFields) {
            fields += '<div class="col-md-1"><input class="form-control" name="removed['+ fieldStart +']" type="text" value="0"></div><div class="col-md-1"><a data-toggle="modal" data-target="#removeRule"><div  id="'+ fieldStart +'" class="removeProduct btn btn-green glyphicon glyphicon-trash trashcan"></div></a></div>';
        }

        // Close row
        fields += '</div>';

        // Append the extra fields
        $('#extraFields').append(fields);
        $('#'+ fieldStart).attr("data-remove", fieldStart);

        // Update the readonly state of the price textbox
        changeDisabledStatePrice();

        fieldStart++;
addRemoveEvent();
    });


Ik heb een kleine aanpassing in je code gedaan die er voor zorgt dat, elke keer als je een element toevoegd, de remove trigger opnieuw op de elementen word gezet.

Probleem is denk ik als volgt :
Laten we beginnen met een aanname, je voert je code uit op document.ready (of iets van gelijke strekking).

Als je dat doet, word het click event toegevoegd voor alle elementen met de class "removeProduct" die op dat moment op je pagina staan.
Echter als je een nieuw element toevoegd zal die dit event nog niet hebben, dus moet je de betreffende code opnieuw uitvoeren. (zoals ik hierboven heb gedaan).

Op het moment dat je dat doet wil je eerst het bestaande click event weg halen (aannemende dat er maar 1 click event op elementen met de class "removeProduct" zit).

De reden dat je dat wil doen is omdat je anders het event 2 (of meer) keer op 1 element hebt staan, en dit kan hele creatieve bugs opleveren. Dus je verwijderd eerst het click event, en vervolgens voeg je het opnieuw toe

Toevoeging op 16/06/2017 07:40:43:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function addRemoveEvent() {
    $('.removeProduct').unbind("click");
    $('.removeProduct').click(function(e) {
        // Determinate if we need to add extra fields or not
        var productRule = ($(this).data('remove'));

        console.log("Clicked removeProduct");
        console.log(productRule);

        $('#modalRemoveButton').click(function(e) {
            console.log("Called removeProduct");
            console.log("ProductRule 1 " + productRule);
            if($('.productName:visible').length == 1) {
                $('#removeRuleError').modal('show');

                console.log("Show error modal");
            } else {
                console.log("ProductRule 2 " + productRule);
                $("input[name='removed["+ productRule + "]'").val('1');
                $('#productLine' + productRule).hide('slow');

                console.log("Removed product");
            }
        });

    });
}

addRemoveEvent();
    /**************************************************************************
    *     dd extra fields to the product pages.
    *
    *      @ Attribute(s)         fields
    *    @ Usage             Set fields to true, to add extra fields
    *    
    ***************************************************************************/
    $('#addField').click(function(e) {
        var addExtraFields = $(this).data('fields');
        var fields = '<div class="row" id="productLine'+ fieldStart +'"><div class="col-md-4"><input class="form-control productName" placeholder="Productnaam" name="productName['+ fieldStart +']" type="text"></div><div class="col-md-1"><input class="form-control" placeholder="Aantal" name="amount['+ fieldStart +']" type="text"></div><div class="col-md-1" style="width: 9.5%"><input class="form-control price" placeholder="Prijs" name="price['+ fieldStart +']" type="text"></div>';

        // If there are extra fields required add them
        if(addExtraFields) {
            fields += '<div class="col-md-1"><input class="form-control" name="removed['+ fieldStart +']" type="text" value="0"></div><div class="col-md-1"><a data-toggle="modal" data-target="#removeRule"><div  id="'+ fieldStart +'" class="removeProduct btn btn-green glyphicon glyphicon-trash trashcan"></div></a></div>';
        }

        // Close row
        fields += '</div>';

        // Append the extra fields
        $('#extraFields').append(fields);
        $('#'+ fieldStart).attr("data-remove", fieldStart);

        // Update the readonly state of the price textbox
        changeDisabledStatePrice();

        fieldStart++;
        addRemoveEvent
    });


Ik heb een kleine aanpassing in je code gedaan die er voor zorgt dat, elke keer als je een element toevoegd, de remove trigger opnieuw op de elementen word gezet.

Probleem is denk ik als volgt :
Laten we beginnen met een aanname, je voert je code uit op document.ready (of iets van gelijke strekking).

Als je dat doet, word het click event toegevoegd voor alle elementen met de class "removeProduct" die op dat moment op je pagina staan.
Echter als je een nieuw element toevoegd zal die dit event nog niet hebben, dus moet je de betreffende code opnieuw uitvoeren. (zoals ik hierboven heb gedaan).

Op het moment dat je dat doet wil je eerst het bestaande click event weg halen (aannemende dat er maar 1 click event op elementen met de class "removeProduct" zit).

De reden dat je dat wil doen is omdat je anders het event 2 (of meer) keer op 1 element hebt staan, en dit kan hele creatieve bugs opleveren. Dus je verwijderd eerst het click event, en vervolgens voeg je het opnieuw toe
Gewijzigd op 16/06/2017 07:41:12 door Jacco Engel
 
Endreaw nvt

Endreaw nvt

16/06/2017 09:18:44
Quote Anchor link
Jacco Engel op 16/06/2017 07:40:41:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
...


Bedankt voor de oplossing, en de duidelijke uitleg. Nu begrijp ik wat er mis ging. Het werkt naar behoren :)
 
Ivo P

Ivo P

16/06/2017 11:06:05
Quote Anchor link
Om dit hele proces te voorkomen, is het misschien handiger om 1 listener te hebben voor het click event, en dan te controleren of het geclickte element de class removeProduct had.

Dan zou je er denk ik al zijn als je de eerste regel

$('.removeProduct').click(function(e) {

vervangt door

$(document).on('click', '.removeProduct', function(e) {


als er nu "ergens" op de pagina (document) geklikt wordt (die click), dan wordt gekeken of (.removeProduct) van toepassing is.
Maar de listener ligt op het hele document. En pas na de click wordt gezocht.
In de oorspronkelijke situatie wordt de listener aan het betreffende element gekoppeld. Is dat element ten tijde van het koppelen niet aanwezig -> geen listener.

Bijkomend voordeel voor de browser is, als het een lijst van 4000 regels is heb je niet 4000 listeners, maar slechts 1.

(ipv document zou je ook nog een kleiner element kunnen kiezen, maar met document ben je er denk ik ook wel)
 
Jacco Engel

Jacco Engel

16/06/2017 12:47:20
Quote Anchor link
Ivo P op 16/06/2017 11:06:05:
Om dit hele proces te voorkomen, is het misschien handiger om 1 listener te hebben voor het click event, en dan te controleren of het geclickte element de class removeProduct had.

Dan zou je er denk ik al zijn als je de eerste regel

$('.removeProduct').click(function(e) {

vervangt door

$(document).on('click', '.removeProduct', function(e) {


als er nu "ergens" op de pagina (document) geklikt wordt (die click), dan wordt gekeken of (.removeProduct) van toepassing is.
Maar de listener ligt op het hele document. En pas na de click wordt gezocht.
In de oorspronkelijke situatie wordt de listener aan het betreffende element gekoppeld. Is dat element ten tijde van het koppelen niet aanwezig -> geen listener.

Bijkomend voordeel voor de browser is, als het een lijst van 4000 regels is heb je niet 4000 listeners, maar slechts 1.

(ipv document zou je ook nog een kleiner element kunnen kiezen, maar met document ben je er denk ik ook wel)


Is inderdaad ook een oplossing, al ben ik er zelf niet zo'n fan van omdat je click handler dan onoverzichtelijk word als je veel events krijgt. Maar dat is meer kwestie van smaak dan iets anders
 
Ivo P

Ivo P

16/06/2017 13:16:05
Quote Anchor link
ik denk dat het juist andersom is:
ipv dat de handlers keer op keer toegevoegd en verwijderd worden.

En daarbij: qua code is het gelijk, op de ene regel na.
Wel heb je gelijk dat de browser bij elke klik ergens op het document alle mogelijke opties
$(document).on('click', '****', function(e) {

na moet lopen of het geklikte element voldoet.

Heb je veel van die opties, dan zou je kunnen kijken of een
<div id="container"> </div> geplaatst kan worden om de betreffende elementen, mocht deze al missen
en dan gebruik maken van
$('#container').on('click', '.removeProduct', function(e) {

Toevoeging op 16/06/2017 13:38:10:

hier wordt het wel mooi uitgelegd:

https://stackoverflow.com/questions/8110934/direct-vs-delegated-jquery-on
 
Thomas van den Heuvel

Thomas van den Heuvel

16/06/2017 14:01:45
Quote Anchor link
Mja met name dat laatste, baken de gebieden af waarbinnen click-events actief zouden moeten zijn, $(document) als selectiegebied is mogelijk nogal overkill.
 
Ivo P

Ivo P

16/06/2017 14:34:14
Quote Anchor link
zoals ik hierboven eerder ook inderdaad al aangaf met "kleiner element".

Maar als ik dat in de eerste post al zou noemen, zou het waarschijnlijk betekenen dat TS ook zijn htmlcode direct moet aanpassen.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.