A2maridz
A2maridz

Reputation: 341

load part of the html page when filtering results with ajax

I want to filter a search results using 3 checkboxs. The results are presented in the div with the id=posts_results

   <div class="checkbox">
      <label><input type="checkbox" id="id1" class="typePost" value="En groupe"> val1 </label>
   </div>
   <div class="checkbox">
      <label><input type="checkbox" id="id2" class="typePost" value="En groupe"> val2 </label>
   </div>
   <div class="checkbox">
      <label><input type="checkbox" id="id3" class="typePost"  value="A domicile"> val3</label>
   </div>
   <div class="checkbox">
      <label><input type="checkbox" id="id4" class="typePost" value="Par webcam"> val4</label>
   </div>

  <div id="posts_results">

            {% include 'posts/posts_results.html' %}

   </div>


    <script>
        $('.typePost').change(function (request, response) {

        var v1=$('#id1').is(":checked")? 1:0;
        var V2=$('#id2').is(":checked")? 1:0;
        var V3=$('#id3').is(":checked")? 1:0;
        var v4=$('#id4').is(":checked")? 1:0;
        $.ajax({

            url: '/posts/type_lesson/',
            dataType: 'json',
            type: "GET",
            data: {
                group: groupChecked,
                webcam: webcamChecked,
                home: homeChecked,
                move: moveChecked,
                distance: distance,
            },
            success: function (object_list) {

                $('#posts_results').load("my_page.html", object_list);
                alert('after')
            }

        });

    });
   <script>

this is my url:

url(r'^filter/$', views.filter, name='filter_type_lesson'),

and this is my view:

def filter(request):
if request.method=='GET':

    #as an exemple I'll send all posts
    data= PostFullSerializer(Post.objects.all(), many=True)
    return JsonResponse(data.data, safe=False)

The filter function excute some filters according to the json sent data, serialize the filtered posts and send them back (in this case I send all the posts as an example).

The results are displayed using a forloop in the div with id "posts_results" and the html is in the file posts_results.html.

The json data are sent but the ajax success function does not update or load the div

and it is also possible to stay

Upvotes: 1

Views: 2453

Answers (2)

Angel F
Angel F

Reputation: 489

maybe you could try to render the template in your view and then load the rendered data in your div.

Supposing your posts/posts_results.html is some as:

<ul>
{% for post in posts %}
    <li> Post: {{post.name }} / Author: {{post.author}} / Date: {{post.created_at}}</li>
{% endid %}
<ul>

In your view, at the moment when you do respective actions, you can render the template and add the html content to the response, ie (based un your current code):

def filter(request):
    if request.method=='GET':
        json_data = {
            "success": False,
            "message": "Some message",
            "result": "some result",
        }
        posts = Post.object.all()
        template = "posts/posts_results.html"

        things_to_render_in_your_template = {
            "posts": posts, # you can add other objects that you need to render in your template
        }

        my_html = get_template(template)
        html_content = my_html.render(things_to_render_in_your_template)

        # here the html content rendered is added to your response
        json_data["html_content"] = html_content
        json_data["success"] = True
        return JsonResponse(json_data)

Then in your JS, at the momento to check ajsx response, you can add the rendered content into your div

$.ajax({

        url: '/posts/type_lesson/',
        dataType: 'json',
        type: "GET",
        data: {
            group: groupChecked,
            webcam: webcamChecked,
            home: homeChecked,
            move: moveChecked,
            distance: distance,
        },
        success: function (response) {
            # response is the json returned from the view, each key defined in your json_data dict in the view, is a key here too 

            # now insert the rendered content in the div
            $('#posts_results').html(response["html_content"]);
            alert('after');
        }

    });

I suggest you instead of create one by one data to your ajax request, use serialize method of jquery or create a FormData object, also instead of GET, use POST to do your request more safe

Upvotes: 0

kagronick
kagronick

Reputation: 2688

I like to stay away from raw POST data as much as possible and let the forms API do the heavy lifting. You can do what you have already with a lot less code in a much more secure way.

Make a form with four BooleanFields named for the BooleanFields in your model. You can override how they are displayed in the HTML with the label variable.

class TheForm(forms.Form):
    my_field = forms.BooleanField(required=False, label="What I want it to say")
    my_field2 = forms.BooleanField(required=False, label="What I want it to say 2", help_text="Something else")
    my_field3 = forms.BooleanField(required=False, label="What I want it to say 3", help_text="Something else")

Output as <form class="my_form">{% csrf_token %}{{form.as_table}}</form>

Submit it with JS like this:

$('.my_form input[type=checkbox]').change(function(e){
    e.preventDefault()
    $.post('module/filer/', $('.my_form').serialize(), function(data) {
        // Handle data
    });
});

When the form is submitted and validated take the cleaned_data attribute and filter your models like this

models = Post.objets.filter(**form.cleaned_data)

This will work because the form fields and named the same as the fields in your model. The same as doing Post.objects.filter(my_field=True, my_field2=True, my_field3=False). Then you can do whatever you want with it. I would use a FormView to do all this:

class MyView(FormView):
    form_class = TheForm

    def form_valid(self, form):
        models = Post.objets.filter(**form.cleaned_data)
        data= PostFullSerializer(data, many=True)
        return JsonResponse(data.data, safe=False)

Now nothing is going to update the div by itself. It is only created when the HTML is initially requested. In your success function you'll need to append your elements manually like this:

$('.my_form input[type=checkbox]').change(function(e){
    e.preventDefault()
    $.post('module/filer/', $('.my_form').serialize(), function(data) {
        var post_results = $('#post_results').html(''); // Clear out old html
        $.each(data, function(item) {
            // Create new divs from ajax data and append it to main div
            var div = $('<div>');
            div.append($('<div>').html(item.my_field));
            div.append($('<div>').html(item.my_field2).addClass('something'));
            div.appendTo(post_results);
        });
    });
});

You can also just past rendered HTML through ajax and do $('#post_results').html(data);. Instead of calling json response you would call self.render_to_response on the FormView.

Upvotes: 1

Related Questions