Jump to content

Updating fields via AJAX on the rendered page


statestreet
 Share

Recommended Posts

As part of the Agile user story system that I'm in the process of building, each story has a list of acceptance tests that go with it. I have this list put together with a repeater, and I've added a checkbox to each test so that developers can mark it off as complete.

What I really want to do, however, is not require developers to edit the page to check things off. They aren't writing the stories, only reading them, so I really want to find a way to give them a checkbox on the rendered page itself that can update the state of the checkbox field when they click it.

The users viewing the page are already logged in (I'm using Adrian's Protected Mode module to lock down the whole site), so It seems like then first step will be to find the right Process API call to save a change to the page. The second step is probably harder, though, making all this happen from Javascript.

Link to comment
Share on other sites

This shouldn't be difficult to do. You just need to add the checkbox to your template so that each story has a checkbox or "Complete" button or such. 

Use some jquery:

$('#checked').click(function(){
    $.ajax( '/change_complete_status.php?pageid=<?php echo $page->id; ?>');
});

Although maybe you need to inject an article id, rather than the entire page id - not sure how you have things set up.

Then in change_complete_status.php

<?php
include("./index.php"); //bootstrap PW

$page_id = (int) wire('input')->get->pageid;
$p = wire('pages')->get($page_id);
$p->of(false);
$p->checked = 1;
$p->save("checked");

Or something along those lines.

  • Like 2
Link to comment
Share on other sites

Wow thanks, that looks much simpler than I thought it would be! The jQuery part makes sense (AJAX call to a new PHP file that makes the PW request) but I'd love to get a better idea of what's going on in those five lines of PHP. I understand wire() just calls PW APIs when bootstrapped, but I'm not clear on what happens after that.

Link to comment
Share on other sites

Well all those lines are doing is getting the page object based on the id that is being sent via the URL, then turning output formatting off (standard procedure before saving a page), setting a field called "checked" to "1" which is the checked status for a checkbox, and then saving that field on the page. I don't expect this code will be an exact solution for you, because I don't know exactly how you have things set up. It was just designed to give you some ideas. If you provide more details, I am sure we can give you more complete - that is if you can't work it out yourself first - it's always good to try first :)

  • Like 1
Link to comment
Share on other sites

So, here's what I have currently: 

$page_id = (int) wire('input')->get->pageid;
$whichindex = (int) wire('input')->get->fieldindex;
$whichfield = (string) wire('input')->get->fieldid;
$p = wire('pages')->get($page_id);
$p->of(false);
$p->acceptance_tests->eq($whichindex)->get($whichfield) = 1;
$whattosave = (string) $p->acceptance_tests->eq($whichindex)->get($whichfield);
$p->save($whattosave);
I've added two other arguments to the URL string that the AJAX calls, first to get first to the matching index of the repeater field on the page, then to one of two checkboxes in that repeater element.

However, I get an error on line 11 about using a method return value in a write context. So apparently I can't use eq() or get() to specify the path to the field to update... but I'm not sure how I should be doing that instead.

Link to comment
Share on other sites

One of my developer co-workers just gave me a few pointers and I've got it working now!

$page_id = (int) wire('input')->get->pageid;
$whichindex = (int) wire('input')->get->fieldindex;
$whichfield = (string) wire('input')->get->fieldid;
$p = wire('pages')->get($page_id);
$p->of(false);
$p->acceptance_tests->eq($whichindex)->set($whichfield, 1);
$p->save("acceptance_tests");

Using set() instead of an '=' operator was all I needed to get around the return value / write context issue, and then I realized I should probably just save the entire repeater field instead of trying to save a part of it. 

Now, however, I come back to another issue that I was having earlier, for which I've only managed a hacky workaround: When checkbox_functions.php is in /templates/, I always get a 403 Forbidden when I try to access it via AJAX. If I just put it in the root, however, it works. I could just leave it this way, but I'd rather follow best practices and keep everything in /site/.

Link to comment
Share on other sites

php files in /site/templates/ are protected against direct access. So you have to create a template and a (hidden) page using this template to use a page with ajax in templates folder.

For example: rename the file to "ajax.php", create a template called "ajax" and a hidden page called "ajax" using this template. Now you can use ajax requests with an url like "http://yourcomain.com/ajax/".

You can combime all your needed ajax stuff in this template. Just pass some "get" parameters with your ajax request like "?action=getuserinfo".

  • Like 4
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

×
×
  • Create New...