1

I have a question over here but was advised to create minimal & reproducible example and this is what I am trying to accomplish right now. On this version, I am trying to show the added nodes from the html results of JQuery/AJAX to the current modal. Please note that the html contents will be dynamically generated using Flask/Jinja, so I cannot target each node that is being added. The JQuery/AJAX part seems to work as the sample element were indeed added to the DOM but upon inspection the element is greyed out and is not being rendered by the browser. How can I do this better (hopefully without additional libraries) so that the added nodes are recognised and rendered properly?

On the topic of creating minimal & reproducible example, since I am new to programming, I have also looked into using online tools such as codepen.io so I could just link the codes here but I am not really sure how to have 2 html codes there (or even simulate the whole flask app online) like I can show here. If you have better idea or better tools I can use when asking questions here, please do share.

FWIW, I have uploaded the codes here.

Please note that it is missing the app.py since codepen will not allow it. It also requires index.html to be on the root which will conflict with my locally saved files since Jinja requires html to be inside templates folder.

The following are the codes.

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'*/
                console.log(data);
                $('#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();
                    // let cont = $(data).find("#targetModalContent").parent().html();
                    // console.log(cont);
                    $('#targetModalContent').html(cont);
                    // $('#targetModalContent').replaceWith(cont);
                }
                else {
                    /* Show success flash message on the modal instead of the original 
                    below nav location --to do*/
                    console.log(data);
                }
            });
    });
});

products.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Bootstrap CSS Offline -->
    <link href="static/css/bootstrap.css" rel="stylesheet">

    <!-- Bootstrap JS Offline-->
    <script src="static/js/jquery-3.5.1.js"></script>
    <script src="static/js/popper.min.js"></script>
    <script src="static/js/bootstrap.js"></script>
    <title>Products</title>
</head>
<body>
    <h2>
        <button type="button" class="btn btn-success" data-toggle="modal"data-target="#modalAdd">
            Add New Product
        </button>
    </h2>
    <!-- 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 New Item</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">
                    <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="description">Product Description</label>
                                    <input class="form-control col-sm-7" id="description" name="description" type="text" value="">
                                </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>

    <script src="static/js/modals.js"></script>
</body>
</html>

results.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Bootstrap CSS Offline -->
    <link href="static/css/bootstrap.css" rel="stylesheet">

    <!-- Bootstrap JS Offline-->
    <script src="static/js/jquery-3.5.1.js"></script>
    <script src="static/js/popper.min.js"></script>
    <script src="static/js/bootstrap.js"></script>
    <title>Products</title>
</head>

<body>
    <h2>
        <button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalAdd">
            Add New Product
        </button>
    </h2>
    <!-- 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 New Item</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">
                    <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="description">Product Description</label>
                                    <input class="form-control col-sm-7" id="description" name="description" type="text"
                                        value="">
                                    <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>

    <script src="static/js/modals.js"></script>
</body>

</html>

app.py

from flask import Flask, render_template, redirect
app = Flask(__name__)


@app.route('/')
@app.route('/products')
def index():
   return render_template("products.html")


@app.route('/products/new', methods=['GET', 'POST'])
def add():
   return render_template("results.html")

if __name__ == '__main__':
   app.run()

The screenshot of the browser view with the source code showing the greyed out elements is here.

Note: The results I get from searching here in stackoverflow is nothing similar to the issue I have.

As suggested by @user2182349 I've now used the built-in snippet editor for the html and the js part of the code. Now I can't get the modal to show on the snippet editor and I don't think I can simulate the AJAX part.

$(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'*/
        console.log(data);
        $('#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();
          // let cont = $(data).find("#targetModalContent").parent().html();
          // console.log(cont);
          $('#targetModalContent').html(cont);
          // $('#targetModalContent').replaceWith(cont);
        } else {
          /* Show success flash message on the modal instead of the original 
          below nav location --to do*/
          console.log(data);
        }
      });
  });
});
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Bootstrap CSS only -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!-- Bootstrap JS only -->  
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
        crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"></script>
    
    
  <title>Products</title>
</head>

<body>
  <h2>
    <button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalAdd">
            Add New Product
        </button>
  </h2>
  <!-- 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 New Item</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">
          <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="description">Product Description</label>
                  <input class="form-control col-sm-7" id="description" name="description" type="text" value="">
                </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>
</body>

</html>
aik3e
  • 131
  • 6
  • Your question is this *I am trying to show the added nodes from the html results of JQuery/AJAX to the current modal.* - use the snippet editor to offer a short section of your code. That will make it much easier for people to give you a good answer. You'll have to add a little bit of code to simulate the Ajax. – user2182349 Jan 22 '21 at 05:30
  • Thank you learnt something new today, -the snippet editor :). Unfortunately, I can't make the modal work from within the snippet editor and I don't think I can simulate the AJAX. – aik3e Jan 22 '21 at 07:14
  • See if you can do it with just the HTML for the modal and JavaScript/jQuery. Breaking the problem into pieces helps. – user2182349 Jan 22 '21 at 12:41
  • 1
    Hi! I've changed the references of the Bootstrap and the JQuery and the modal is showing now. I still don't know though how to simulate the AJAX call. Any ideas? – aik3e Jan 25 '21 at 08:13
  • Thank you @Don'tPanic. You are right. the response from AJAX call is the results.html. The results.html is dynamically generated from a flask route with WTF validations, so depending on the user input, the validation result varies. I will try though if I could isolate the specific elements, but first, I'll try the parsehtml. – aik3e Jan 25 '21 at 10:57
  • @Don'tPanic, I've just tried the parseHTML method and it is still the same. JQuery seems to load the nodes on the DOM based on what I could see from the inspector on the developer tools of the browser. Just like [here](https://i.stack.imgur.com/xS1lu.png) under the `
    Product combination is already enrolled.
    ` . They are still greyed out and the browser doesn't render them. Any other suggestion?
    – aik3e Jan 26 '21 at 08:20
  • Hmm you are right, it looks like doing `$(data)` is enough. [This answer](https://stackoverflow.com/questions/7159426/using-jquery-to-search-a-string-of-html) demonstrates it well, and I set up [a simple JSFiddle](https://jsfiddle.net/dont_panic/7L36wmsa/) which confirms. I will delete my previous comment as it is wrong and just adds confusion. – Don't Panic Jan 26 '21 at 09:09

0 Answers0