a-ok Posted January 16, 2017 Share Posted January 16, 2017 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 More sharing options...
LostKobrakai Posted January 16, 2017 Share Posted January 16, 2017 It certainly is possible, but there's currently not much processwire would give you out of the box in terms of an implementation. You'd need to write that on your own. Link to comment Share on other sites More sharing options...
kongondo Posted January 16, 2017 Share Posted January 16, 2017 This is a multi-part question, so lets try to break it down. The normal workflow resembles the following: Data is requested on the client-side. In your case, this is via ajax. You'll need JavaScript code to send the ajax request 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 You process the ajax request by sanitizing and whitelisting the inputs You send a response back, normally as JSON, but could be xml, or whatever JavaScript code receives the response and manipulates the DOM (aka updating the page without refresh) How Tos How to Work with Ajax Driven Content: 1, 2 See #1 See input, sanitize, + search forums using these terms for more examples . See #1 See #1 4 Link to comment Share on other sites More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 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 More sharing options...
kongondo Posted January 16, 2017 Share Posted January 16, 2017 (edited) 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 January 16, 2017 by kongondo Link Link to comment Share on other sites More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 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 More sharing options...
fbg13 Posted January 16, 2017 Share Posted January 16, 2017 <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]); } 1 Link to comment Share on other sites More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 @fbg13 This looks super useful. Can I ask... what is 'ajaxURL'? Should this be the page where the PHP you included should exist? Link to comment Share on other sites More sharing options...
fbg13 Posted January 16, 2017 Share Posted January 16, 2017 @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 More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 @fbg13 Super appreciate the help. I seem to get an error with '$sanitize' as if the JSON is thinking it's a JS variable? Any thoughts? Link to comment Share on other sites More sharing options...
fbg13 Posted January 16, 2017 Share Posted January 16, 2017 @oma It's sanitizer, i forgot the r, updated the code too. Link to comment Share on other sites More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 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 More sharing options...
fbg13 Posted January 16, 2017 Share Posted January 16, 2017 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. Link to comment Share on other sites More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 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 More sharing options...
kongondo Posted January 16, 2017 Share Posted January 16, 2017 (edited) ProcessWire will not allow you to directly access .php files in various folders, including /site/... See that post for the options available to you. Edited January 16, 2017 by kongondo Link to comment Share on other sites More sharing options...
fbg13 Posted January 16, 2017 Share Posted January 16, 2017 @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 More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 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 More sharing options...
a-ok Posted January 16, 2017 Author Share Posted January 16, 2017 Think I'll try this... ob_start(); include('./inc/training-item.inc'); $out .= ob_get_contents(); ob_end_clean(); Link to comment Share on other sites More sharing options...
BitPoet Posted January 16, 2017 Share Posted January 16, 2017 Have a look at wireRenderFile, it does the output buffering stuff for you. $out .= wireRenderFile('./inc/training-item.inc', array('p' => $p)); 2 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now