2016-07-16 5 views
0

Ich habe ein Formular in meinem HTML, das geklont und dynamisch angehängt wird, wenn der Benutzer den #addOne-Button drückt. Das Formular wird erfolgreich auf Eingabefehler überprüft. Das einzige Problem, mit dem ich derzeit konfrontiert bin, ist, dass es nicht korrekt für Bilder funktioniert. Nehmen wir an, ich lade ein Bild für das erste Formular hoch, es funktioniert perfekt. Aber wenn ich auf den Button #addOne klicke und ein Bild für das zweite Formular hochlade, dann treten die Probleme auf. Bevor sogar ein Bild für das zweite Formular hochgeladen wird, zeigt es bereits das Bild aus dem vorherigen Formular auf der Seite an. Wenn Sie ein Bild für dieses Formular hochladen, wird Formular 2 nicht aktualisiert. Vielmehr wird das angezeigte Bild von 1 geändert. Wie kann ich sicherstellen, dass jedes Formular sein eigenes hochgeladenes Bild anzeigt und ordnungsgemäß validiert wird? Hier ist mein jsFiddlejQuery-Bildvalidierung für dynamisch geklontes Formular

HTML

<div class="article_properties"> 

    <form class="article_properties_form" action="" method="POST" enctype="multipart/form-data"> 
    <p style="display: inline">Page Number</p> 
    <div style="background-color: #FF355E; padding: 5px; display: inline; margin-left: 5px"> 

     <p style="display: inline" class="pageNumber"></p> 
    </div> 
    <textarea style="display: none" class="inputNumber" name="pages"></textarea> 
    <p>Image</p> 
    <input style="padding: 0px" type="file" name="image" class="pageImg"> 
    <div class="imgContainer"> 
    </div> 
    <p>Subtitle</p> 
    <input type="text" name="subtitle"> 

    <p>Text</p> 
    <textarea name="text" rows="4"></textarea> 
    <input id="properties_btn" type="submit" value="Submit/Update" name="properties_submit"> 
    <hr style="border: 1px dotted lightgray; margin-bottom: 50px"> 
    </form> 


    <a style="display: none; text-align: center; margin: 50px; font-size: 25px" class="expand" href="#"> 

    </a> 
</div> 
<!--End of article properties div--> 
<div id="addOne"> 
    <p>+Add page</p> 
</div> 

<div class="nextBtn" style="display: none"> 
    <p>Finalize my article</p> 
</div> 

jQuery

var numPagesTemp = 4; 
$('.pageNumber:last').text(numPagesTemp); 
$('.inputNumber:last').text(numPagesTemp); 
//Invoke functions for first form 
add_validation_for_forms(); 
add_image_construction(); 

//Form validation 
function add_validation_for_forms() { 
    $(".article_properties_form").each(function() { 
    $(this).validate({ 
     errorElement: 'div', 

     rules: { 
     image: { 
      required: true, 
      extension: "jpg|jpeg|png", 
      minImageSize: { 
      width: 600, 
      height: 400 
      } 
     }, 

     subtitle: { 
      required: true, 
      minlength: 2, 
      maxlength: 25 
     }, 
     text: { 
      required: true, 
      minlength: 35, 
      maxlength: 275 
     } 
     }, 

     messages: { 
     image: { 
      required: "This page needs an image", 
      extension: "You're only allowed to upload jpg or png images." 
     }, 

     subtitle: { 
      required: "You have to provide a subtitle for this page!", 
      minlength: "Your subtitle must be at least 2 characters long", 
      maxlength: "Your subtitle must be less than 25 characters long" 
     }, 
     text: { 
      required: "Please enter text for this page", 
      minlength: "Your text must be at least 35 characters long", 
      maxlength: "Your text must be less than 275 characters long" 
     }, 
     }, 
    }); 
    }); 
} 
//Adding a form 
$('#addOne').click(function() { 

    numPagesTemp--; 

    var articlePropsTemplate = $('.article_properties_form:last').clone(); 
    articlePropsTemplate.show(); 
    $('.article_properties').append(articlePropsTemplate); 

    var articlePropsExpand = $('.expand:last').clone(); 
    articlePropsExpand.text("Expand " + numPagesTemp); 
    articlePropsExpand.hide(); 

    $('.article_properties').append(articlePropsExpand); 

    $('.pageNumber:last').text(numPagesTemp); 
    $('.inputNumber:last').text(numPagesTemp); 
    articlePropsTemplate[0].reset(); 
    add_validation_for_forms(); 

    add_image_construction(); 
    articlePropsTemplate.validate().resetForm(); 

    if (numPagesTemp == 1) { 
    $('#addOne').hide(); 
    $(".nextBtn").show(); 
    } 

}); 

//Adding Method 
$.validator.addMethod('minImageSize', function(value, element, minSize) { 
    var imageSize = $(element).data('imageSize'); 
    return (imageSize) && (imageSize.width >= minSize.width) && (imageSize.height >= minSize.height); 
}, function(minSize, element) { 
    return ($(element).data('imageSize')) ? ("Your image's size must be at least " + minSize.width + "px by " + minSize.height + "px") : "Selected file is not an image."; 
}); 

//Image Uploading 
var $properties_btn = $('properties_btn'), 
    $imgContainer = $('.imgContainer'), 
    $pageImg = $('.pageImg'); 

function add_image_construction() { 

    $('.pageImg').change(function() { 
    $pageImg.removeData('imageSize'); 
    $imgContainer.hide().empty(); 

    var file = this.files[0]; 

    if (file.type.match(/image\/.*/)) { 
     $properties_btn.attr('disabled', true); 

     var reader = new FileReader(); 

     reader.onload = function() { 
     var $img = $('<img />').attr({ 
      src: reader.result 
     }); 

     $img.on('load', function() { 
      $imgContainer.append($img).show(); 

      $pageImg.data('imageSize', { 
      width: $img.width(), 
      height: $img.height() 
      }); 

      $img.css({ 
      width: '400px', 
      height: '200px' 
      }); 

      $properties_btn.attr('disabled', false); 

      validator.element($pageImg); 
     }); 
     } 

     reader.readAsDataURL(file); 
    } else { 
     validator.element($pageImg); 
    } 
    }); 
} 
+0

Hinweis, geklont 'form' würde erstellen doppelte' id' '# properties_btn' in' document' – guest271314

+0

@ guest2713148 hmm die Form ohne die Bilddimension Validierung perfekt funktioniert, aber damit es vermasselt – user2896120

+0

Should Bild von geklonten entfernt werden 'Form'? – guest271314

Antwort

1

Mein Rat, wenn das Klonen ist dies:

nie Elemente klonen, die instrumentiert wurden.

Mit instrumentiert, ich meine, sie haben JavaScript-Verhalten auf ihnen eingerichtet, wie Ereignisbehandlung.

tun statt wie im Folgenden:

(1) die Elemente klonen, bevor sie in einer Variablen den Klon instrumentiert worden ist und halten.

var $CLONED_FORM = $('.article_properties_form:first').clone(); 

(2) Stellen Sie eine Funktion bereit, die den Satz von zu klonenden Elementen instrumentiert.

function initializeForm($form, pageNum) { 
    // Set up form validation here. 
    // Also attach the change-event handler for the file input here. 
} 

(3) Rufen Sie die Funktion für die Sätze auf, die sich bereits auf der Seite befinden.

$('.article_properties_form').each(function() { 
    initializeForm($(this), numPagesTemp--); 
}); 

(4) Wenn Sie einen anderen Satz der Elemente hinzufügen möchten, Klon der Klon und fügen Sie es, und die Funktion auf es nennen.

$('#addOne').click(function() { 
    var $newForm = $CLONED_FORM.clone().appendTo('.article_properties').show(); 

    initializeForm($newForm, numPagesTemp--); 

    if (numPagesTemp == 0) { 
    $('#addOne').hide(); 
    $(".nextBtn").show(); 
    } 
}); 

jsfiddle


Sie müssen auch den Validator Objekt in einer Variablen validator Namen speichern.

var validator = $form.validate({ 

Außerdem sollten Sie doppelte id Werte vermeiden, wenn das Klonen. Sie haben eine id auf der Schaltfläche Senden, aber es scheint nicht benötigt zu werden, also können Sie vielleicht nur das entfernen.

+0

Alles funktioniert wie es jetzt sollte! Danke vielmals! – user2896120

0

Ich brauche meinen Code zu verwenden

Bearbeiten,

Substituierte class="properties_btn" für id="properties_btn"

aktualisiert Duplikat zu verhindern id- document angehängt wird; definiert validator bei change Ereignis.

$(function() { 
 
    var numPagesTemp = 4; 
 
    $('.pageNumber:last').text(numPagesTemp); 
 
    $('.inputNumber:last').text(numPagesTemp); 
 
    //Invoke functions for first form 
 
    add_validation_for_forms(); 
 
    add_image_construction(); 
 

 
    //Form validation 
 
    function add_validation_for_forms() { 
 
     $(".article_properties_form").each(function() { 
 
     $(this).validate({ 
 
      errorElement: 'div', 
 

 
      rules: { 
 
      image: { 
 
       required: true, 
 
       extension: "jpg|jpeg|png", 
 
       minImageSize: { 
 
       width: 600, 
 
       height: 400 
 
       } 
 
      }, 
 

 
      subtitle: { 
 
       required: true, 
 
       minlength: 2, 
 
       maxlength: 25 
 
      }, 
 
      text: { 
 
       required: true, 
 
       minlength: 35, 
 
       maxlength: 275 
 
      } 
 
      }, 
 

 
      messages: { 
 
      image: { 
 
       required: "This page needs an image", 
 
       extension: "You're only allowed to upload jpg or png images." 
 
      }, 
 

 
      subtitle: { 
 
       required: "You have to provide a subtitle for this page!", 
 
       minlength: "Your subtitle must be at least 2 characters long", 
 
       maxlength: "Your subtitle must be less than 25 characters long" 
 
      }, 
 
      text: { 
 
       required: "Please enter text for this page", 
 
       minlength: "Your text must be at least 35 characters long", 
 
       maxlength: "Your text must be less than 275 characters long" 
 
      }, 
 
      }, 
 
     }); 
 
     }); 
 
    } 
 
    //Adding a form 
 
    $('#addOne').click(function() { 
 

 
    numPagesTemp--; 
 

 
    var articlePropsTemplate = $('.article_properties_form:last') 
 
     .clone(); 
 
    articlePropsTemplate.find("img").remove(); 
 
    $('.article_properties').append(articlePropsTemplate); 
 

 
    var articlePropsExpand = $('.expand:last').clone(); 
 
    articlePropsExpand.text("Expand " + numPagesTemp); 
 
    articlePropsExpand.hide(); 
 

 

 
    $('.article_properties').append(articlePropsExpand); 
 

 
    $('.pageNumber:last').text(numPagesTemp); 
 
    $('.inputNumber:last').text(numPagesTemp); 
 
    $("form:last")[0].reset(); 
 
    add_validation_for_forms(); 
 

 
    // add_image_construction(); 
 
    articlePropsTemplate.validate().resetForm(); 
 

 
    if (numPagesTemp == 1) { 
 
     $('#addOne').hide(); 
 
     $(".nextBtn").show(); 
 
    } 
 
    
 

 
    }); 
 

 
    //Adding Method 
 
    $.validator.addMethod('minImageSize', function(value, element, minSize) { 
 
    var imageSize = $(element).data('imageSize'); 
 
    return (imageSize) && (imageSize.width >= minSize.width) && (imageSize.height >= minSize.height); 
 
    }, function(minSize, element) { 
 
    return ($(element).data('imageSize')) ? ("Your image's size must be at least " + minSize.width + "px by " + minSize.height + "px") : "Selected file is not an image."; 
 
    }); 
 

 
    //Image Uploading 
 
    // var $properties_btn = $('.properties_btn'), 
 
    // $imgContainer = $('.imgContainer'), 
 
    // $pageImg = $('.pageImg'); 
 

 
    function add_image_construction() { 
 

 
    $(document).on("change", ".pageImg", function(e) { 
 
     var form = $(this).closest("form"); 
 
     var validator = form.validate(); 
 
     $(this).removeData('imageSize'); 
 
     form.find('.imgContainer').hide().empty(); 
 

 
     var file = this.files[0]; 
 

 
     if (file.type.match(/image\/.*/)) { 
 
     form.find('.properties_btn').attr('disabled', true); 
 

 
     var reader = new FileReader(); 
 

 
     reader.onload = function() { 
 
      var $img = $('<img />').attr({ 
 
      src: reader.result 
 
      }); 
 

 
      $img.on('load', function() { 
 
      form.find('.imgContainer').append($img).show(); 
 

 
      $(e.target).data('imageSize', { 
 
       width: $img.width(), 
 
       height: $img.height() 
 
      }); 
 

 
      $img.css({ 
 
       width: '400px', 
 
       height: '200px' 
 
      }); 
 

 
      form.find('.properties_btn').attr('disabled', false); 
 

 
      validator.element(e.target); 
 
      }); 
 
     } 
 

 
     
 
     reader.readAsDataURL(file); 
 
     } else { 
 
     validator.element(e.target); 
 
     } 
 
     
 
    }); 
 
    } 
 
    
 
})
form { 
 
    border: 1px solid blue; 
 
    padding: 10px; 
 
    margin: 10px; 
 
}
<script src="https://code.jquery.com/jquery-3.0.0.js"></script> 
 
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.15.0/jquery.validate.min.js"></script> 
 
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.15.0/additional-methods.min.js"></script> 
 
<div class="article_properties"> 
 

 
    <form class="article_properties_form" action="" method="POST" enctype="multipart/form-data"> 
 
    <p style="display: inline">Page Number</p> 
 
    <div style="background-color: #FF355E; padding: 5px; display: inline; margin-left: 5px"> 
 

 
     <p style="display: inline" class="pageNumber"></p> 
 
    </div> 
 
    <textarea style="display: none" class="inputNumber" name="pages"></textarea> 
 
    <p>Image</p> 
 
    <input style="padding: 0px" type="file" name="image" class="pageImg"> 
 
    <div class="imgContainer"> 
 
    </div> 
 
    <p>Subtitle</p> 
 
    <input type="text" name="subtitle"> 
 

 
    <p>Text</p> 
 
    <textarea name="text" rows="4"></textarea> 
 
    <input class="properties_btn" type="submit" value="Submit/Update" name="properties_submit"> 
 
    <hr style="border: 1px dotted lightgray; margin-bottom: 50px"> 
 
    </form> 
 

 

 
    <a style="display: none; text-align: center; margin: 50px; font-size: 25px" class="expand" href="#"> 
 

 
    </a> 
 
</div> 
 
<!--End of article properties div--> 
 
<div id="addOne"> 
 
    <p>+Add page</p> 
 
</div> 
 

 
<div class="nextBtn" style="display: none"> 
 
    <p>Finalize my article</p> 
 
</div>


Dies ist eine vereinfachte Version von dem, was Sie erreichen wollen, ohne

Datei hochgeladen Validieren

// maximum number of `form` elements which `document` should contain 
 
var n = 4; 
 
// display `form` index 
 
function handleLabel() { 
 
    $("label").html(function(index, html) { 
 
    return "form #" + index 
 
    }) 
 
} 
 

 
handleLabel(); 
 

 
function processFile() { 
 
    // preview uploaded image 
 
    $("<img>", {src: URL.createObjectURL(this.files[0])}) 
 
    .insertAfter(this.nextElementSibling).after("<br>"); 
 
    
 
} 
 
// handle file upload; delegate event to `document` 
 
$(document).on("change", ":file", processFile); 
 
// append cloned `form` to page 
 
$("button").on("click", function() { 
 
    // if less than `n` forms 
 
    if ($("form").length < 4) { 
 
    // copy last `form` `.outerHTML` instead of using `.clone()` 
 
    $($("form:last")[0].outerHTML) 
 
    // remove `img` from `html` 
 
    .find("img").remove().end() 
 
    .insertAfter("form:last"); 
 
    // update `form` `label` elements 
 
    handleLabel(); 
 
    } else { 
 
    // detach `click` event from `button` 
 
    // when four `form` elements exist in `document` 
 
    $(this).off("click") 
 
    } 
 
}); 
 
// handle `form` submit event 
 
$(document).on("submit", "form", function(e) { 
 
    var img = $(this).find("img")[0]; 
 
    // check `img` `width`, `height` 
 
    if (img.naturalWidth < 600 
 
    || img.naturalHeight < 400) { 
 
     e.preventDefault(); 
 
     this.reset(); 
 
     alert("invalid img width or height") 
 
    } 
 
})
form { 
 
    border: 1px solid blue; 
 
    padding: 10px; 
 
    margin: 10px; 
 
}
<script src="https://code.jquery.com/jquery-3.0.0.js"></script> 
 
<form> 
 
    <fieldset> 
 
    <label></label><br> 
 
    <input name="file" type="file" accept=".jpg,.jpeg,.png" required /> 
 
    <br> 
 
    <input type="submit" /> 
 
    </fieldset> 
 
</form> 
 
<button> 
 
    add form 
 
</button>

jsfiddle https://jsfiddle.net/hLjvffpv/5/

+0

@ user2896120 jsfiddle https://jsfiddle.net/hLjvffpv/1/ – guest271314

+0

Wie kann ich das mit dem was ich habe implementieren? – user2896120

+0

Ich habe 'jquery-validate' nicht ausprobiert, obwohl Sie das' required' Attribut in '' Element einfügen können und das 'accept' Attribut in' accept = "umwandeln. Jpg, .jpeg, .png "', um das Hochladen von '.jpg',' .jpeg' oder '.png' Datei-Uploads vor dem' form'-Einreichen zu erfordern. – guest271314

Verwandte Themen