activeCheckbox with ajax

I want to update mysql with the state of a checkbox as soon as it is checked or unchecked. I have no problem with the controller action, however I am having trouble with the activeCheckbox statement. I am not familiar with jquery though I have been reading some tutorials,and do not understand how the checkbox value will be transferred. I have the following code currently in my view page:




<?php echo CHtml::activeCheckbox($page,'pageActive',array('ajax'=>array(

   'url'=>$this->createUrl("site/activatePage", array('pageID'=>$page->pageID,'pageActive'=>'js:this.value')),

   'type'=>'POST'

   ))

  );

?>



Unfortunately, this doesn’t work and I haven’t been able to figure this out. I’d appreciate any help someone could provide.

Bob

It was answered on this forum

http://www.yiiframework.com/forum/index.php?/topic/3110-ajax-and-sidebar/page__p__17286__fromsearch__1&#entry17286

(and more…)

instead of ‘data’=>‘id=’.$model->id,

use ‘js:this.value’ or assign an ID to this html element (using ‘attributes’ param of the Yii activeCheckbox) and get it’s value with $(’#yourID’).val() (see http://docs.jquery.com/Val) … probably(?) like this:

‘data’=>‘checkboxVal=’.‘js:$("#yourID").val()’,

and put your ajax function in event ‘onclick’ or ‘onchange’ attribute of the chechbox.

hopefully explanation isn’t too complicated. it suppose that you have had some practice with Yii.

It was clear that I needed a better understanding of both Yii and jquery, so I decided to read some more about jquery and try to do it without using activeCheckbox so that I could just tackle one problem at a time. This was how I was able to get it to work with jquery without using activeCheckbox:

view page:




<script type="text/javascript">

$(function() {

  $(".checktest").click(function() {

    var id = $(this).attr("id");

    if($(this).is(':checked'))

    {

      var checkval = 1;

    } else

    {

      var checkval = 0;

    }

    var string = 'id='+ id + '&checkval='+ checkval;


    $.ajax({

      type: "POST",

      url: "/index.php/site/testresponse",

      data: string,

      dataType: "json",

      success: function(response){

        if(response.checkval == 1)    

        {

          $("#"+response.id).attr('checked', true);

        } else

        {

          $("#"+response.id).removeAttr('checked');

        }

      }

    });

    return false;

  });   

});

</script>

  <input type="checkbox" id="5" value="1" class="checktest">Test Checkbox<br />



controller action:




    public function actionTestResponse()

    {

          $id = $_POST['id'];

          $checkval = $_POST['checkval'];

        //update database 

          $response = array('id'=>$id,'checkval'=>$checkval);

          echo json_encode($response);

    }



I am not sure how to render this using activeCheckbox. Checkboxes don’t seem to be as simple as many of the examples for links, text field and such I’ve seen looking through this forum because their value doesn’t really tell you anything about their state (checked or unchecked), so you have to use an ‘if’ statement.

Plus when an ajax function is started the checkbox is cleared so you have to recheck it if necessary after getting the response which means you have to pass the ‘id’ and checked value back to jquery as it also loses track of the element ($(this) no longer has any value). Does activeCheckbox take care of either of those issues without additional code? If not, what advantage would using activeCheckbox provide?

If someone could provide an equivalent code using activeCheckbox I would appreciate it.

Thanks,

Bob

Good exercise B)

Here I push functionality out of the view:




<script type="text/javascript">

$(function() {

  $(".checktest").click(function() {

    $.post(

      "testresponse",

      {id : $(this).attr("id"), checkval : $(this).is(':checked')},

      function(response) { $("#" + response.id).attr('checked', response.checkval); },

      "json"

    );

  });

});

</script>


<input type="checkbox" id="5" value="1" class="checktest" />Test Checkbox






public function actionTestResponse() {

  $id = $_POST['id'];

  $checkval = $_POST['checkval'] == 'true' ? true : false;

# update database

  $response = array('id' => $id, 'checkval' => $checkval);

  echo json_encode($response);

}



Note that you also have a problem with a numeric ID. ID and NAME must begin with a letter ([A-Za-z]).

Regarding your questions:

Checkbox state is boolean. Just pass that boolean state to where you need it. Of course, HTML converts a boolean to a string, so you have to handle it as such. Alternatively, you can wrap up the AJAX parameters as a JSON object and pass that along. (See the toJSON extension to jQuery.)

I don’t know why you had the problem with the checkbox changing state. The version I posted will work fine if you comment out the AJAX callback.

$(this) should still work, but remember that AJAX is asynchronous, so (pretty much) anything you do after making the call needs to go into the callback function. To make this clear, it’s quite common to pass the callback function in the calling parameters:




$.get("details/displayproduct.php", {},	function(data) {displayproduct(response);} );



If you need to retain the handle – for an ID you can always get it again anyway – then you need to save it with something like:




var pThis=$(this)



But this is not something I would personally recommend.

Thanks for looking at this. Your code is definitely superior to mine and I have rewritten it following your design. After that I was able to remove the callback function without it unchecking the checkbox, as you found. I don’t know why it was doing it for me before.

I think I’ll just stick with plain HTML and jquery instead of trying to do this sort of thing with activeCheckbox.

Thanks again, I appreciate the help. It has reminded me to make use of ternary statements as well.

Cool, glad it helped. The rule of thumb of all OO is to push things where they belong; it’s not always obvious at all! I think you are wise to consider the CHTML helpers just that, helpers.

I’m new to Yii, but I think things like this make sense to be turned into a widget.

Just one more thing, if I may, note the absence of if-statements in what I did. (Okay, there’s a ternary, but that’s because of HTTP, and I could get rid of it by passing a JSON object.)

In OO-land, whenever you think of writing an if-statement have a think why. It’s completely natural in procedural programming – you have no choice – but in OO it’s often a sign that things need to be simplified. The Yii core could do with some love in this area!