JQuery/AJAX call function seems to run only once and JQuery selector on AJAX result only yields the inner html

拈花ヽ惹草 提交于 2021-02-08 11:30:30

问题


I am new to programming and this is also my first question on this platform. I have tried implementing applicable solutions I could find here for similar questions raised but is still stuck. Should you believe that a previously answered question might answer mine, please share the link to such answer. Also please correct me should you find that I have broken some guidelines on how to properly ask questions on this platform.

Now, on to the actual issues.

The following are the relevant sections (please, let me know if I have missed something that might be relevant). The issues are stated on my comments on modals.js.

modals.js

$(document).ready(function(){
    $('#frmAddProduct').on('submit', function aj (event) {
        event.preventDefault();
        $.ajax({
            cache: false,
            type : 'POST',
            url : '/products/new',
            data : $('#frmAddProduct').serialize(),
            datatype: 'html' 
        })
        .done(function process (data) {
            /* The modal has to be shown unless the user clicks on 'close'*/
            $('#modalAdd').modal('show'); 
            let err = $(data).find(".invalid-feedback").html();
            if (err){
                /* replace the contents of the modal with section from 
                ajax result to show validation messages*/
                let cont = $(data).find("#targetModalContent").html();
                $('#targetModalContent').html(cont);
                /* Once the code above executes, clicking the submit button again 
                terminates the whole process.
                Maybe this section requires a loop or recursion? But this part
                is already on the "on submit" listener, right?*/
            }
            else {
                /* Show success flash message on the modal instead of the original 
                below nav location */
                console.log(data);
                let msg = $(data).closest("#targetFlash").html();
                /* using the .find doesn't work and results in msg=undefined.
                I don't understand why that is the case, I tried using .parent
                but it also did not work, or maybe I was using the .parent improperly.
                I also tried $($(data).closest("#targetFlash")).parent().html but
                it too didn't worked.

                Why is it returning only the message and not the whole node 
                with the enclosing div?
                */
                $('#frmAddProduct fieldset>div:first').prepend(msg);
            }
        });
    }); 
});

products.html

{% extends "tblayout.html" %}
<!-- Main Content -->
{% block thead %}
{% endblock %}
{% block tbody %}
{% endblock %}
{% block tfoot %}
{% endblock %}
{% block maincont %}
    <!-- ModalAdd -->
    <div class="modal fade" id="modalAdd" tabindex="-1" role="dialog" aria-labelledby="modalAddTitle" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
            <div class="modal-content" id="targetModalContent">
                <div class="modal-header">
                    <h5 class="modal-title" id="modalAddLongTitle">Add {{ legend }}</h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <form method="POST" action="" id="frmAddProduct">
                    {{ formAdd.csrf_token }}
                    <div class="modal-body">
                        <div class="container-fluid">
                            <fieldset class="form-group">
                                <div class="form-group row">
                                    {{ formAdd.productSubCategory.label(class="col-form-label col-sm-5") }}
                                    {% if formAdd.productSubCategory.errors %}
                                    {{ formAdd.productSubCategory(class="form-control col-sm-7 is-invalid") }}
                                    <div class="invalid-feedback">
                                        {% for error in formAdd.productSubCategory.errors %}
                                        <span class="col-sm-7 offset-5">{{ error }}</span>
                                        {% endfor %}
                                    </div>
                                    {% else %}
                                    {{ formAdd.productSubCategory(class="form-control col-sm-7") }}
                                    {% endif %}
                                </div>
                                <div class="form-group row">
                                    {{ formAdd.brand.label(class="col-form-label col-sm-5") }}
                                    {% if formAdd.brand.errors %}
                                    {{ formAdd.brand(class="form-control col-sm-7 is-invalid") }}
                                    <div class="invalid-feedback">
                                        {% for error in formAdd.brand.errors %}
                                        <span class="col-sm-7 offset-5">{{ error }}</span>
                                        {% endfor %}
                                    </div>
                                    {% else %}
                                    {{ formAdd.brand(class="form-control col-sm-7") }}
                                    {% endif %}
                                </div>
                                <div class="form-group row">
                                    {{ formAdd.description.label(class="col-form-label col-sm-5") }}
                                    {% if formAdd.description.errors %}
                                    {{ formAdd.description(class="form-control col-sm-7 is-invalid") }}
                                    <div class="invalid-feedback">
                                        {% for error in formAdd.description.errors %}
                                        <span class="col-sm-7 offset-5">{{ error }}</span>
                                        {% endfor %}
                                    </div>
                                    {% else %}
                                    {{ formAdd.description(class="form-control col-sm-7") }}
                                    {% endif %}
                                </div>
                            </fieldset>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <div>
                            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        </div>
                        <div>
                            {{ formAdd.submit(class="btn btn-primary") }}
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
    
{% endblock %}
<!-- Optional Body scipt loaded after the main content has loaded -->
{% block bodyscript %}
<script src="../static/js/modals.js"></script>
{% endblock %}

AJAX result on Issue #1

 <!-- ModalAdd -->
    <div class="modal fade" id="modalAdd" tabindex="-1" role="dialog" aria-labelledby="modalAddTitle" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
            <div class="modal-content" id="targetModalContent">
                <div class="modal-header">
                    <h5 class="modal-title" id="modalAddLongTitle">Add Product</h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <form method="POST" action="" id="frmAddProduct">
                    <input id="csrf_token" name="csrf_token" type="hidden" value="ImNlZDc1Njc0MTY4NTg5NTNhNDg0NWEyNGYyZjYzZmIyYmFmMTZhZmQi.YAamUA.WGi03w__AklqccdIQgK_pWG5oJg">
                    <div class="modal-body">
                        <div class="container-fluid">
                            <fieldset class="form-group">
                                <div class="form-group row">
                                    <label class="col-form-label col-sm-5" for="productSubCategory">Product Sub-Category</label>
                                    
                                    <select class="form-control col-sm-7 is-invalid" id="productSubCategory" name="productSubCategory" required><option selected value="1">ProductCategory1, ProductSubCategory1</option><option value="2">ProductCategory1, ProductSubCategory2</option><option value="3">ProductCategory2, ProductSubCategory3</option></select>
                                    <div class="invalid-feedback">
                                        
                                        <span class="col-sm-7 offset-5">Product combination is already enrolled.</span>
                                        
                                    </div>
                                    
                                </div>
                                <div class="form-group row">
                                    <label class="col-form-label col-sm-5" for="brand">Brand</label>
                                    
                                    <select class="form-control col-sm-7 is-invalid" id="brand" name="brand" required><option selected value="1">Brand1</option><option value="2">Brand2</option><option value="3">Brand3</option></select>
                                    <div class="invalid-feedback">
                                        
                                        <span class="col-sm-7 offset-5">Product combination is already enrolled.</span>
                                        
                                    </div>
                                    
                                </div>
                                <div class="form-group row">
                                    <label class="col-form-label col-sm-5" for="description">Product Description</label>
                                    
                                    <input class="form-control col-sm-7 is-invalid" id="description" name="description" placeholder="New Product" required type="text" value="45">
                                    <div class="invalid-feedback">
                                        
                                        <span class="col-sm-7 offset-5">Product combination is already enrolled.</span>
                                        
                                    </div>
                                    
                                </div>
                            </fieldset>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <div>
                            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        </div>
                        <div>
                            <input class="btn btn-primary" id="submit" name="submit" type="submit" value="Add Product">
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>

AJAX result on Issue #2 (I have copied only the target div since the rest of the html data is just the same, this is right below the nav)

<div class="alert alert-success" id="targetFlash">
        Product 45 has been added!
    </div>

main.routes.py

@main.route("/products", methods=['GET', 'POST'])
@login_required
def products():
    formAdd = frmAddProduct()
    formMod = frmModProduct()
    q = sess.query(Product.id.label("PId"),
                    Product.description.label("PDesc"),
                    Product.isactive.label("PIsactive"),
                    ProductSubCategory.id.label("PSCid"),
                    ProductCategory.description.label("PCDesc"),
                    ProductSubCategory.description.label("PSCDesc"),
                    Brand.id.label("BId"), Brand.name.label("BName"))\
                    .select_from(Product)\
                    .join(ProductSubCategory)\
                    .join(ProductCategory)\
                    .join(Brand)\
                    .all()
    page = request.args.get('page', 1, type=int)
    qp = paginate.Page(q, items_per_page=5, page=page)
    data = sqlaq2dict(qp)
    npage = qp.pager(url= url_for('main.products') + "?page=$page",
                    link_attr=dict({'class':'btn btn-outline-primary mb-4'}),
                    curpage_attr=dict({'class':'btn btn-primary mb-4'}),
                    dotdot_attr=dict())
    pagenav = Markup(npage)
    return render_template("products.html", title='Products', legend='Product',
                            data=data, pagenav=pagenav, formAdd=formAdd, formMod=formMod)


@main.route("/products/new", methods=['POST'])
@login_required
def addProduct():
    formAdd = frmAddProduct()
    if formAdd.validate_on_submit():
        p = Product()
        p.productSubCategory_id = formAdd.productSubCategory.data
        p.brand_id = formAdd.brand.data
        p.description = formAdd.description.data
        p.isactive = formAdd.isactive.data
        syncNext('management', 'Product', 'id') # Ensures right ID for Postgres
        sess.add(p)
        sess.commit()
        flash(
            f'Product {formAdd.description.data} has been added!', 'success')
        # return jsonify({"status" : "success"}) #Cannot have multiple returns
        return redirect(url_for('main.products'))
    return render_template("products.html", title='Products', legend='Product',
                           formAdd=formAdd)

forms.py

class frmAddProduct(FlaskForm):
    # productSubCategories = sess.query(ProductSubCategory.id,\
    #                         ProductSubCategory.fullDesc)\
    #                         .filter(ProductSubCategory.isactive==True)\
    #                         .all()
    psc = sess.query(ProductCategory.description.label("PCDesc"),
                     ProductSubCategory.id.label("PSCId"), 
                     ProductSubCategory.description.label("PSCDesc"))\
                    .join(ProductSubCategory)\
                    .all()
    pscDict = sqlaq2dict(psc) #Converts the resulting tuple to dict
    productSubCategories = []
    for r in pscDict:
        i = (r['PSCId'], r['PCDesc'] + ', ' + r['PSCDesc'])
        productSubCategories.append(i)
        
    productSubCategory = SelectField('Product Sub-Category', 
                                    choices=productSubCategories,
                                    coerce=int,
                                    validators=[InputRequired()])
    brands = sess.query(Brand.id, Brand.name)\
            .filter(Brand.isactive == True)\
            .all()
    brand = SelectField('Brand', choices=brands, coerce=int,
                                     validators=[InputRequired()])
    description = StringField('Product Description', validators=[
        DataRequired()], render_kw={"placeholder": "New Product"})
    isactive = BooleanField('Status', default=True)
    submit = SubmitField('Add Product')
    #---------------------------------------------Should be composite Key
    def validate_productSubCategory(self, productSubCategory):
        user = sess.query(Product)\
            .filter(Product.productSubCategory_id == self.productSubCategory.data,
                    Product.brand_id == self.brand.data, Product.description ==
                    self.description.data)\
            .first()
        if user:
            raise ValidationError('Product combination is already enrolled.')

    def validate_brand(self, brand):
        user = sess.query(Product)\
            .filter(Product.productSubCategory_id == self.productSubCategory.data,
                    Product.brand_id == self.brand.data, Product.description ==
                    self.description.data)\
            .first()
        if user:
            raise ValidationError('Product combination is already enrolled.')

    def validate_description(self, description):
        user = sess.query(Product)\
            .filter(Product.productSubCategory_id == self.productSubCategory.data,
                    Product.brand_id == self.brand.data, Product.description ==
                    self.description.data)\
            .first()
        if user:
            raise ValidationError('Product combination is already enrolled.')

来源:https://stackoverflow.com/questions/65788720/jquery-ajax-call-function-seems-to-run-only-once-and-jquery-selector-on-ajax-res

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!