使用Play Framework 2使用动态创建的表单输入更新数据库

时间:2014-01-08 23:06:49

标签: java javascript jquery playframework ebean

我有一个候选人模型和一些其他模型,如学校,学位,技能,工作岗位等,与候选人模型有一对多的关系。

我能够创建一个创建表单(创建新候选人的表单),可以使用javascript / jquery动态创建表单字段。用户可以通过单击“添加另一个按钮”来添加更多输入字段。表单提交给控制器,所有数据都可以完美地添加到数据库中。

问题与编辑表单有关。编辑表单与创建表单几乎相同,只是它在数据库的表单字段中预先填充了数据。当我将此表单提交给控制器中的更新功能时,它会更新错误。当我返回编辑表单以查看它是否正常工作时,会有随机输入字段,其中包含空白值,但数据会被编辑。

我对游戏框架相当新,可能我做错了。我使用Codeigniter在PHP中做了类似的事情,它运行良好。可能是因为Codeigniter不使用Ebean或JPA。

下面是我写的一些代码,所以我的问题更容易理解。我只会包括候选模型和学校模型,因为其他模型类似于学校模型。另外,我包含了生成动态表单字段的js代码。

非常感谢任何帮助!

Candidate.java(model):

    @Entity
    public class Candidate extends Model {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long id;

    public String firstName;

    public String lastName;

    public boolean sponsorshipStatus;

    public boolean proceedToInterview;

    @Column(columnDefinition = "TEXT")
    public String text;

    @OneToMany(cascade = CascadeType.ALL)
    public List<School> schools;

    @OneToMany(cascade = CascadeType.ALL)
    public List<Degree> degrees;

    @OneToMany(cascade = CascadeType.ALL)
    public List<Document> documents;

    @OneToMany(cascade = CascadeType.ALL)
    public List<JobPosition> jobPositions;

    @OneToMany(cascade = CascadeType.ALL)
    public List<Skill> skills;

    /**
     * Generic query helper for entity Candidate with id Long
     */
    public static Model.Finder<Long, Candidate> find = new Model.Finder<Long, Candidate>(Long.class, Candidate.class);

    public static Page<Candidate> page(int page, int pageSize, String sortBy, String order, String filter) {
    return find.where()
            .ilike("first_name", "%" + filter + "%")
            .orderBy(sortBy + " " + order)
            .findPagingList(pageSize)
            .setFetchAhead(false).getPage(page);
    }

    }


School.java(model):

    @Entity 
    public class School extends Model {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    public String schoolName;

    @ManyToOne
    public Candidate candidate;


    /**
     * Generic query helper for entity Company with id Long
     */
    public static Model.Finder<Long, School> find = new Model.Finder<Long, School>(
            Long.class, School.class);

        }

Application.java(controller):



    public class Application extends Controller {

    public static Result index() {
        return ok(index.render("Your new application is ready."));
    }

    /*display a list of candiates*/

    public static Result list(int page, String sortBy, String order, String filter) {
        return ok(views.html.list.render(Candidate.page(page, 10, sortBy, order, filter), sortBy, order, filter));
    }

    /**
     * Display the 'edit form' of a existing Candidate.
     * 
     * @param id
     *            Id of the candidate to edit
     */
    public static Result edit(Long id) {
        Form<Candidate> candidateForm =    form(Candidate.class).fill(Candidate.find.byId(id));
        Candidate candidate = Candidate.find.byId(id);
        return ok(views.html.editForm.render(id, candidateForm, candidate));
    }

    /**
     * Handle the 'edit form' submission
     * 
     * @param id
     *            Id of the computer to edit
     */
    public static Result update(Long id) {
        RequestBody request_body = request().body();
        MultipartFormData body = request_body.asMultipartFormData();

        // MultipartFormData FilePart object list
        List<FilePart> files = body.getFiles();
        List<Document> docs = new ArrayList<Document>();

        for (FilePart file : files) {
            String fileName = file.getFilename();
            // Use Java.IO File class to move file in desired location
            File f = file.getFile();

            File nf = new File("\\\\WL-MSAMARITONI\\Images", fileName);
            f.renameTo(nf);

            Document doc;
            doc = new Document();

            doc.docName = fileName;
            doc.filePath = nf.getAbsolutePath();
            docs.add(doc);

        }
        Form<Candidate> candidateForm = form(Candidate.class).bindFromRequest();
        Candidate updateCandidate = candidateForm.get();
        updateCandidate.documents = docs;
        /*while(updateCandidate.degrees.remove(null));
        while(updateCandidate.jobPositions.remove(null));
        while(updateCandidate.schools.remove(null));
        while(updateCandidate.skills.remove(null));
        while(updateCandidate.documents.remove(null));
    */

        updateCandidate.update(id);
        updateCandidate.save();
        flash("success", "Candidate " + candidateForm.get().firstName + " has been     created");
        return redirect("/candidate/" + id);

    }

    /**
     * Display the 'new candidate form'.
     */
    public static Result create() {
        Form<Candidate> candidateForm = form(Candidate.class);
        return ok(views.html.createForm.render(candidateForm));
    }

    /**
     * Handle the 'new candidate form' submission
     */
    public static Result save() {

        RequestBody request_body = request().body();
        MultipartFormData body = request_body.asMultipartFormData();

        // MultipartFormData FilePart object list
        List<FilePart> files = body.getFiles();
        List<Document> docs = new ArrayList<Document>();

        for (FilePart file : files) {
            String fileName = file.getFilename();
            // Use Java.IO File class to move file in desired location
            File f = file.getFile();

            File nf = new File("\\\\WL-MSAMARITONI\\Images", fileName);
            f.renameTo(nf);

            Document doc;
            doc = new Document();

            doc.docName = fileName;
            doc.filePath = nf.getAbsolutePath();
            docs.add(doc);

        }
        Form<Candidate> candidateForm = form(Candidate.class).bindFromRequest();
        Candidate newCandidate = candidateForm.get();
        newCandidate.documents = docs;
        newCandidate.save();

        flash("success", "Computer " + candidateForm.get().firstName + " has been   created");
        return redirect("/candidates/new");
    }

    }




createForm.scala.html(view):

    @(candidateForm: Form[Candidate])

    @import helper._


    @main("Create Candidate"){

    <h1>Add a New Candidate</h1>

     @form(routes.Application.save(), args= 'class -> "form-horizontal",'enctype ->       "multipart/form-data") {
     <div class="row">
     <fieldset class="span6">
        <legend>
            <h3> Add Candidate Info</h3>
        </legend>
        @inputText(candidateForm("firstName"), '_label -> "First Name")
        @inputText(candidateForm("lastName"), '_label -> "Last Name")
        @checkbox(candidateForm("sponsorshipStatus"), '_label -> "Sponsorship   Status")
        @checkbox(candidateForm("proceedToInterview"), '_label -> "Proceed to  Interview")
        @textarea(candidateForm("text"), args = 'rows -> 3, 'cols -> 50, '_label -> "Notes")
    </fieldset>
    <fieldset class="span6">
        <legend>
            <h3>Add Schools</h3>
        </legend>
        <div id="schools" class="control-group">
            <div class="school hidden_form_default">
                <input id="chk_school" type="checkbox">
                <input disabled="disabled" id="school" name="schools[].schoolName" placeholder="Enter School">
            </div>
            <div class="school">
                <input id="chk_school_0" type="checkbox" value="1">
                <input id="school_0" name="schools[0].schoolName"   placeholder="Enter School" >
            </div>
        </div>
        <button class="btn school_add_button">
            Add Another
        </button>
        <button class="btn btn-danger school_delete_button">
            Delete Checked
        </button>
    </fieldset>
</div>
    <div class="row">
        <fieldset class="span6">
            <legend>                              

    <h3>Add Degrees</h3>
             </legend>
        <div id="degrees" class="control-group">
            <div class="degree hidden_form_default">
                <input id="chk_degree"  class="" type="checkbox" value="1">
                <input id="degreeLevel" disabled="disabled" class="" name="degrees[].degreeLevel" placeholder="Degree Level" >
                <input id="degreeFocus" disabled="disabled" class="" name="degrees[].degreeFocus" placeholder="Degree Focus" >
                <input type="text" id="completedDate" disabled="disabled" class="datepicker input-small" name="degrees[].completedDate" placeholder="Completed" >
            </div>
            <div class= "degree">
                <input id="chk_degree_0" class="" type="checkbox" value="1">
                <input id="degreeLevel_0" class="" name="degrees[0].degreeLevel" placeholder="Degree Level" >
                <input id="degreeFocus_0" class="" name="degrees[0].degreeFocus" placeholder="Degree Focus" >
                <input type="text" id="completedDate_0" class="datepicker input-small" name="degrees[0].completedDate" placeholder="Completed" >
            </div>
        </div>
        <button class="btn degree_add_button">
            Add Another
        </button>
        <button class="btn btn-danger degree_delete_button">
            Delete Checked
        </button>
    </fieldset>
    <fieldset class="span6">
        <legend>
            <h3>Add Skills</h3>
        </legend>
        <div id="skills" class="control-group">
            <div class="skill hidden_form_default">
                <input id="chk_skill" type="checkbox">
                <input disabled="disabled" id="skill" name="skills[].skill" class="clearMeFocus" placeholder="Enter skill">
            </div>
            <div class="skill">
                <input id="chk_skill_0" type="checkbox" value="1">
                <input id="skill_0" name="skills[0].skill" class="clearMeFocus" placeholder="Enter skill" >
            </div>
        </div>
        <button class="btn skill_add_button">
            Add Another
        </button>
        <button class="btn btn-danger skill_delete_button">
            Delete Checked
        </button>
    </fieldset>
</div>
    <div class="row">
        <fieldset class="span6">
            <legend>

    <h3>Add Desired Positions</h3>
            </legend>
        <div id="positions" class="control-group">
            <div class="position hidden_form_default">
                <input id="chk_position"  class="" type="checkbox" value="1">
                <input id="position" disabled="disabled" class="" name="jobPositions[].position" placeholder="Enter Position" >
            </div>
            <input id="chk_position_0" class="" type="checkbox" value="1">
            <input id="positionLevel_0" class="" name="jobPositions[0].position" placeholder="Enter Position" >

        </div>
        <button class="btn position_add_button">
            Add Another
        </button>
        <button class="btn btn-danger position_delete_button">
            Delete Checked
        </button>
    </fieldset>
        <fieldset class="span6">
        <legend>
            <h3>Add Documents</h3>
        </legend>
        <div id="documents" class="control-group">
            <div class="document hidden_form_default">
                <input id="chk_document" type="checkbox">
                <input type="file" disabled="disabled" id="document" name="documents[]">
            </div>
            <div class="document">
                <input id="chk_document_0" type="checkbox" value="1">
                <input id="document_0" type="file" name="documents[0]" >
            </div>
        </div>
        <button class="btn document_add_button">
            Add Another
        </button>
        <button class="btn btn-danger document_delete_button">
            Delete Checked
        </button>
    </fieldset>

    </div>
    <button type="submit"  class="btn btn-primary control">
    Add Candidate
    </button>

    }
    }


editForm.scala.html(view)

    @(id: Long, candidateForm: Form[Candidate], candidate: Candidate)

    @import helper._

    @main("Edit Candidate") {

    <h1>Edit Candidate</h1>

    @form(routes.Application.update(id), args= 'class -> "form-horizontal",'enctype ->     "multipart/form-data", 'id -> "updateForm") {

    <div class="row">
    <fieldset class="span6">
        <legend>

    <h3> Edit Candidate Info</h3>
        </legend>
        @inputText(candidateForm("firstName"), '_label -> "First Name")
        @inputText(candidateForm("lastName"), '_label -> "Last Name")
        @checkbox(candidateForm("sponsorshipStatus"), '_label -> "Sponsorship Status")
        @checkbox(candidateForm("proceedToInterview"), '_label -> "Proceed to Interview")
        @textarea(candidateForm("text"), args = 'rows -> 3, 'cols -> 50, '_label -> "Notes")
    </fieldset>
    <fieldset class="span6">
        <legend>
            <h3>Add Schools</h3>
        </legend>


        <div id="schools" class="control-group">
            <div class="school hidden_form_default">
                <input id="chk_school" type="checkbox">
                <input disabled="disabled" id="school" name="schools[].schoolName" placeholder="Enter School">
            </div>
            @for(school <- candidate.schools) {
            <div class="school">
                <input id="chk_school_@school.id" type="checkbox" value="@school.id">
                <input id="school_@school.id" name="schools[@school.id].schoolName" value="@school.schoolName" placeholder="Enter School" >
                <input type="hidden" id="schoolId_@school.id" class="" name="schools[@school.id].id" value="@school.id">
            </div>


            } 
            <div class="school new_field_div">
                <input id="chk_school_0" type="checkbox" value="1">
                <input id="school_0" name="schools[0].schoolName" placeholder="Enter School" >
            </div>

        </div>
        <button class="btn school_add_button">
            Add Another
        </button>
        <button class="btn btn-danger school_delete_button">
            Delete Checked
        </button>
    </fieldset>
</div>
    <div class="row">
        <fieldset class="span6">
        <legend>

    <h3>Add Degrees</h3>
        </legend>
        <div id="degrees" class="control-group">
            <div class="degree hidden_form_default">
                <input id="chk_degree"  class="" type="checkbox" value="1">
                <input id="degreeLevel" disabled="disabled" class="" name="degrees[].degreeLevel" placeholder="Degree Level" >
                <input id="degreeFocus" disabled="disabled" class="" name="degrees[].degreeFocus" placeholder="Degree Focus" >
                <input type="text" id="completedDate" disabled="disabled" class="datepicker input-small" name="degrees[].completedDate" placeholder="Completed" >
            </div>
            @for(degree <- candidate.degrees) {
                <div class ="degree">
                    <input id="chk_degree_@degree.id" class="" type="checkbox" value="@degree.id">
                    <input id="degreeLevel_@degree.id" class="" name="degrees[@degree.id].degreeLevel" value="@degree.degreeLevel" placeholder="Degree Level" >
                    <input id="degreeFocus_@degree.id" class="" name="degrees[@degree.id].degreeFocus" value="@degree.degreeFocus" placeholder="Degree Focus" >
                    <input type="hidden" id="degreeId_@degree.id" class="" name="degrees[@degree.id].id" value="@degree.id">

                    <input type="text" id="completedDate_@degree.id" class="datepicker input-small" name="degrees[@degree.id].completedDate" value="@degree.completedDate" placeholder="Completed" >
                </div>
            }

            <div class ="degree new_field_div">
                <input id="chk_degree_0" class="" type="checkbox" value="1">
                <input id="degreeLevel_0" class="" name="degrees[0].degreeLevel" placeholder="Degree Level" >
                <input id="degreeFocus_0" class="" name="degrees[0].degreeFocus" placeholder="Degree Focus" >
                <input type="text" id="completedDate_0" class="datepicker input-small" name="degrees[0].completedDate" placeholder="Completed" >
            </div>
        </div>
        <button class="btn degree_add_button">
            Add Another
        </button>
        <button class="btn btn-danger degree_delete_button">
            Delete Checked
        </button>
    </fieldset>
    <fieldset class="span6">
        <legend>
            <h3>Add Skills</h3>
        </legend>
        <div id="skills" class="control-group">
            <div class="skill hidden_form_default">
                <input id="chk_skill" type="checkbox">
                <input disabled="disabled" id="skill" name="skills[].skill" class="clearMeFocus" placeholder="Enter skill">
            </div>
            @for(skill <- candidate.skills) {
                <div class="skill">
                    <input id="chk_skill_@skill.id" type="checkbox" value="@skill.id">
                    <input id="skill_@skill.id" name="skills[@skill.id].skill" class="clearMeFocus" value="@skill.skill" placeholder="Enter skill" >
                    <input type="hidden" id="skillId_@skill.id" class="" name="skills[@skill.id].id" value="@skill.id">
                </div>
            }
            <div class="skill new_field_div">
                <input id="chk_skill_0" type="checkbox" value="1">
                <input id="skill_0" name="skills[0].skill" class="clearMeFocus" placeholder="Enter skill" >
            </div>
        </div>
        <button class="btn skill_add_button">
            Add Another
        </button>
        <button class="btn btn-danger skill_delete_button">
            Delete Checked
        </button>
    </fieldset>
</div>
    <div class="row">
    <fieldset class="span6">
        <legend>

    <h3>Add Desired Positions</h3>
        </legend>
        <div id="positions" class="control-group">
            <div class="position hidden_form_default">
                <input id="chk_position"  class="" type="checkbox" value="1">
                <input id="position" disabled="disabled" class="" name="jobPositions[].position" placeholder="Enter Position" >
            </div>
            @for(position <- candidate.jobPositions) {
                <div class="position">
                    <input id="chk_position_@position.id" class="" type="checkbox" value="@position.id">
                    <input id="positionLevel_@position.id" class="" name="jobPositions[@position.id].position" value="@position.position" placeholder="Enter Position" >
                    <input type="hidden" id="positionId_@position.id" class="" name="jobPositions[@position.id].id" value="@position.id">
                </div>
            }
            <div class="position new_field_div">
                <input id="chk_position_0" class="" type="checkbox" value="1">
                <input id="positionLevel_0" class="" name="jobPositions[0].position" placeholder="Enter Position" >
            </div>
        </div>
        <button class="btn position_add_button">
            Add Another
        </button>
        <button class="btn btn-danger position_delete_button">
            Delete Checked
        </button>
    </fieldset>
    <fieldset class="span6">
        <legend>
            <h3>Add Documents</h3>
        </legend>
        <div id="documents" class="control-group">
            <div class="document hidden_form_default">
                <input id="chk_document" type="checkbox">
                <input type="file" disabled="disabled" id="document" name="documents[]">
            </div>
            @for(document <- candidate.documents) {
                <div class="document">
                    <input id="chk_document_@document.id" type="checkbox" value="@document.id">
                    <input type="hidden" id="documentId_@document.id" class="" name="documents[@document.id].id" value="@document.id">
                    <p>@document.docName</p>
                </div>
            }

            <div class="document new_field_div">
                <input id="chk_document_0" type="checkbox" value="1">
                <input id="document_0" type="file" name="documents[0]" >
            </div>
        </div>
        <button class="btn document_add_button">
            Add Another
        </button>
        <button class="btn btn-danger document_delete_button">
            Delete Checked
        </button>
    </fieldset>

</div>

    <div class="actions">
    <input type="submit" value="Save this Candidate" class="btn primary">
    or <a href="@routes.Application.list()" class="btn">Cancel</a>
    </div>
    }


    }


main.js:

    $(function () {
    var delete_form_url = "/school/delete"
    add_another_form_field('.school_add_button', '.school', '#schools', 'schoolName', '.school_delete_button', delete_form_url);
    add_another_form_field('.degree_add_button', '.degree', '#degrees', 'degreeName', '.degree_delete_button', delete_form_url);
    add_another_form_field('.skill_add_button', '.skill', '#skills', 'skillName', '.skill_delete_button', delete_form_url);
    add_another_form_field('.position_add_button', '.position', '#positions', 'positionName', '.position_delete_button', delete_form_url);
    add_another_form_field('.document_add_button', '.document', '#documents', 'documentName', '.document_delete_button', delete_form_url);
    $('.datepicker').datepicker();

    $("#updateForm").submit(function (event) {

        $(".new_field_div").each(function () {
            var isNull = false;
            var new_field_inputs = $(this).find("input:text");

            new_field_inputs.each(function (index, element) {
                console.log($(element).val());
                if ($(element).val()) {
                    isNull = false;
                    return false;
                } else {
                    isNull = true;
                }

            });
            if (isNull) {
                $(this).remove();
            }

        });

    });

    });

    function add_another_form_field(add_button_class, child_div_class, parent_element_id,    field_name, delete_button_class, delete_form_url) {
    var num = 1;
    $(add_button_class).on("click", function (event) {
        event.preventDefault();

        var cloned_fields = $(child_div_class + ":first").clone();
        console.log(cloned_fields);
        cloned_fields.find('input,textarea,select').attr('id', function (i, val) {
            if (val !== undefined) {
                return val + '_' + num;
            }
        });

        cloned_fields.find('label').attr('for', function (i, val) {
            if (val !== undefined) {
                return val + '_' + num;
            }
        });
        cloned_fields.find('input,textarea,select').attr('name', function (i, val) {
            if (val !== undefined) {
                return val.replace(/\[\]/, "[" + num + "]");
            }
        });

        cloned_fields.removeClass("hidden_form_default");
        cloned_fields.addClass("new_field_div");

        cloned_fields.find('input').prop('disabled', false);

        cloned_fields.appendTo(parent_element_id);
        num++;

        // clear the new inputs on click
        // clear input on focus
        $(".clearMeFocus").focus(function () {
            if ($(this).val() == $(this).attr("title")) {
                clearMePrevious = $(this).val();
                $(this).val("");
            }
        });

        // if field is empty afterward, add text again
        $(".clearMeFocus").blur(function () {
            if ($(this).val() == "") {
                $(this).val(clearMePrevious);
            }
        });

    });

    $(delete_button_class).click(function (event) {
        event.preventDefault();
        var form = $(this).parents('form');
        var table_name = form.find('input[name="table_name"]').val();
        $(child_div_class).find('input[type="checkbox"]:checked:enabled').each(function  (index, child) {
            table_row_id = $(child).val();
            if (table_row_id) {
                $.post(delete_form_url, {
                    table_name: table_name,
                    table_row_id: table_row_id
                });
            }
            // delete from view

            $(child).parents().remove(child_div_class);
        });

    });

    }

0 个答案:

没有答案