Jump to content

Updating $pages query via AJAX (for filters etc)


a-ok
 Share

Recommended Posts

I'm wanting to set up a list of filters (that would change the original $pages query) and wondered if this was possible to do via AJAX with PW?

<?php $limit = 20; $exercises = $pages->find("parent=/uddannelse/, sort=-training_detail_date, limit=$limit"); ?>

For example, I might implement a sort filter (A-Z or DATE) which would update the 'sort' field to '-name' rather than '-training_detail_date'. Or, I might implement a category filter so on click it would update the $pages query to:

<?php $limit = 20; $exercises = $pages->find("parent=/uddannelse/, sort=-training_detail_date, training_detail_category=123, limit=$limit"); ?>

Any thoughts? Thanks.

Link to comment
Share on other sites

This is a multi-part question, so lets try to break it down. The normal workflow resembles the following:

  1. Data is requested on the client-side. In your case, this is via ajax. You'll need JavaScript code to send the ajax request
  2. The request is either sent to the current page or to a named url, i.e. you could have a dedicated page to receive the ajax request
  3. You process the ajax request by sanitizing and whitelisting the inputs
  4. You send a response back, normally as JSON, but could be xml, or whatever
  5. JavaScript code receives the response and manipulates the DOM (aka updating the page without refresh)

How Tos

  1. How to Work with Ajax Driven Content: 1, 2
  2. See #1
  3. See input, sanitize, + search forums using these terms for more examples :-)
  4. See #1
  5. See #1

 

  • Like 4
Link to comment
Share on other sites

Thanks both.

I thought as much. I knew I could implement some form filtering and call the results via AJAX but I thought perhaps there was a way to manipulate the $pages query per click. I realise it's a pretty dumb question in hindsight.

Link to comment
Share on other sites

Nothing dumb about the question. Of course you can still manipulate the $pages query per click. That's what you do here:

if($config->ajax) {
    	// process $trainingDetail here..
	// ...some code
	// you page query here
	$results = $pages->find("template=basic-page, limit=10, sort=$trainingDetail");
	foreach($results as $r) $array[] = $r->title;
	echo json_encode($array);
	exit;
}

// in JavaScript, do something with the JSON

You need to be careful though about the server load in case there will be lots of ajax requests. Caching, client and/or server-side mitigates against that.

Example Ajax request + $pages query in the Gif here.

Edited by kongondo
Link
Link to comment
Share on other sites

Thanks @kongondo!

What I've done previously to create the filters as a form (as I had multiple filters) that push the selected filters into an input then I retrieve these using $input->get which would update a $pages query on a new page. I'm wondering if this is possible without using a form. I'll keep thinking. Thanks for your help.

Link to comment
Share on other sites

 

<div class="onClick" data-letter="a">A</div>
<div class="onClick" data-letter="b">B</div>

<div class="content">Contains default data that will get replaced by ajax data</div>

 

$('.onClick').on('click', function(){
	var letter = $(this).data('letter'); // gets the value of data-letter from the clicked element
	$.ajax({
		url: ajaxUrl,
		type: 'POST',
		dataType: 'json',
		data: {
          		// post variables
			'action': 'filterPages',
			'letter': letter
		},
	}).done(function(data){
		$('.content').html(data.html);
      		// or 
		// $('.content').append(data.html);
      		// or 
		// $('.content').preppend(data.html);
      
	})
})

 

if($this->config->ajax && $this->input->post->action == "filterPages") {
	$letter = $sanitizer->selectorValue($this->input->post->letter);
	$p = $pages->get("template=templateName, name^={$letter}");
	$out = "<div>{$p->title}</div>";
	return json_encode(["html" => $out]);
}

 

  • Like 1
Link to comment
Share on other sites

@oma Yes

1 hour ago, kongondo said:

The request is either sent to the current page or to a named url

If you use the current page you can access the page fields by using $page->fieldname.

If you use a separate page you have to send the page id with the request if you need it.

Link to comment
Share on other sites

37 minutes ago, fbg13 said:

@oma It's sanitizer, i forgot the r, updated the code too.

Ah yes I missed that too :(

If I was calling a separate page, so I could run a nice loop template, is there any reason why it would return a 500 server error?

Say, in /site/ajax/ajax.php I had your PHP code and in the JS I had url: rootURL + 'site/ajax/ajax.php', is there anything that would throw this off? It works fine within the same page... just not when I request the ajax.php file.

 

Link to comment
Share on other sites

8 minutes ago, fbg13 said:

Maybe you can't access php files directly, not sure.

I have an ajax template and a page, using the template, that i use as the ajax url.

Okay I'll maybe go down that route.

One last thing; if I am wanting to loop through results ($pages->find) rather than ($pages->get) what's the best way to do this? I can output it as PHP but unsure how to do it as JSON data for the AJAX call?

Link to comment
Share on other sites

@oma you process the loop in php 

if($this->config->ajax && $this->input->post->action == "filterPages") {
	$letter = $sanitizer->selectorValue($this->input->post->letter);
	$pages_ = $pages->find("template=templateName, name^={$letter}");
	$out = "";
	foreach($pages_ as $p) {
		$out .= "<div>";
		$out .= "<h3>{$p->title}</h3>";
		$out .= "<img src='{$p->image->first()->url}'>";
		$out .= "</div>";
	}
	return json_encode(["html" => $out]);
}

 

Link to comment
Share on other sites

7 minutes ago, fbg13 said:

@oma you process the loop in php 


if($this->config->ajax && $this->input->post->action == "filterPages") {
	$letter = $sanitizer->selectorValue($this->input->post->letter);
	$pages_ = $pages->find("template=templateName, name^={$letter}");
	$out = "";
	foreach($pages_ as $p) {
		$out .= "<div>";
		$out .= "<h3>{$p->title}</h3>";
		$out .= "<img src='{$p->image->first()->url}'>";
		$out .= "</div>";
	}
	return json_encode(["html" => $out]);
}

 

Is there a way to do this without including the HTML markup as part of the $out?

For example...

foreach ($pages_ as $p) {
	include('./inc/training-item.inc');
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...