2

Update

After experimenting more with the solution(s) from: How do I bind to list of checkbox values with AngularJS? I am a bit closer. This is what I've updated my <input type="checkbox"> to:

<input
type="checkbox"
name="items[]"
value="{{ $item['item_id'] }}"
ng-checked="formData.items.indexOf({{$item['item_id']}}) > -1"
ng-click="toggleSelection({{$item['item_id']}})"
/>    

Now, I can see the data being updated/logged to the console and watching the HTML via dev-tools I can see the checked="checked" being added to the element. Although still not checked visually.

I think for now, I will resort to using jQuery's $.post() method and continue my quest for getting a better handle on AngularJS fundamentals before attempting such types of trickery... probably better to now mix/mash my PHP/Blade/AngularJS so much anyway.

End Update

I am fairly new to AngularJS and am looking to integrate it into an existing Laravel 4 application (mostly for submitting/processing forms Asynchronously).

The problem I am running into, in short, is that the checkbox portion of the form is not behaving as I expected. Somehow AngularJS (I've narrowed it down to the problem happening when I encapsulate the code with the <div ng-app> </div>) is making my checkboxes funky.

When I click the checkboxes they immediately "Uncheck". However, the data is passed through to my main.js on ng-submit. Somehow they are being checked... without being checked visually. Makes perfect sense right?

I've been in and out of multiple articles, so here I am :) :

The snippets below are mostly based on Scotch.io's: http://scotch.io/tutorials/javascript/submitting-ajax-forms-the-angularjs-way

The AngularJS docs on Checkboxes: http://docs.angularjs.org/api/ng.directive:input.checkbox

and a number of Stack Overflow articles (notably this one): How do I bind to list of checkbox values with AngularJS?

I guess it boils down to me wanting to generate the form with PHP/Laravel/Blade and just hand off the submission action/processing to AngularJS. I know I could convert the majority of this work to AngularJS/JavaScript, but for now would prefer to stick with the PHP generated form and insert the proper AngularJS attributes throughout.

Really, it is almost working for me (The text input field is submitting and being processed as I expected).

Is there a better/simpler way for me to handle a list/array of checkbox values?

PHP Generated Form (with AngularJS attributes) -> AngularJS Magic/Submit/Functions -> PHP Process Data Return Results -> $http.success -> AngularJS Functions/$scope -> Reflect /ResultsChanges in HTML Form/Data

<!-- Snippet Pull out From HTML -->
<div ng-app="formApp">
    <form ng-submit="processForm()" ng-controller="MyFormController" id="the_form" name="the_form">

        <!-- Verify the two-way binding. This updates successfully on ng-submit="processForm()" -->
        <h1>@{{message}}</h1>

        <!-- This submits/binds successfully ... -->
        <input ng-model="formData.test_message" type="text" name="test_message" class="input-lg">

        @foreach($array_items as $item)
            <a>
                <label for="{{ $item['item_id'] }}">
                    <!-- These Checkboxes will not Check! (Visually) ... However the data does show up successfully in the JavaScript console.dir($.param( $scope.formData) ); -->
                    <input type="checkbox" ng-model="formData.items.{{ $item['item_id'] }}" value="{{ $item['item_id'] }}" />
                    Label Text Here!
                </label>
            </a>
        @endforeach
        <button>Submit That!</button>
    </form>
</div>



<!-- Snippet from JavaScript -->
<script>
var formApp = angular.module('formApp', []);

function MyFormController($scope, $http) {

    $scope.formData = {};
    $scope.message = "Just another default message";
    $scope.items = {};

    $scope.processForm = function() {

        console.log("The Dir!");
        console.dir($.param( $scope.formData) );
        console.log("The Dir!");

        /**
         * Ignoring this method until data/html/form is taken care of
         */
        return
        // $http({
        //     method  : 'POST',
        //     url     : '/myapi/theurl',
        //     data    : $.param($scope.formData),  // pass in data as strings
        //     headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
        // })
        //     .success(function(data) {
        //         console.log(data);
        //         if (!data.success) {
        //             $scope.message = "Fail";
        //         } else {
        //             $scope.message = data.message;
        //         }
        //     });
    };
}
</script>
Community
  • 1
  • 1
Erik Aybar
  • 4,761
  • 1
  • 23
  • 29
  • 1
    If all you're doing is sending and receiving POST data I'd just use jquery `$.post('', $('form').serialize(), function(){ // handle business });` Personally I don't always use angular especially for small things like this. – Michael J. Calkins Dec 30 '13 at 19:25
  • Just in case: http://api.jquery.com/serialize/ and http://api.jquery.com/jquery.post/ Also checkout `serializeArray` if `serialize` doesn't workout. If you'd like I can submit this as a more complete answer. – Michael J. Calkins Dec 30 '13 at 19:26
  • Admittedly that is probably the solution I need to go with for now. I have just been teetering on the brink of using AngularJS for a bit now and thought I would try to squeeze it in. Thanks @MichaelCalkins for reminding me that simpler is often better. ... as for really getting my hands dirty with AngularJS. That may have to wait for another day. And what a day that will be! ... The problem still perplexes me, but I think this will get me thinking in the right direction for the future. – Erik Aybar Dec 30 '13 at 19:30
  • I hear you, I've done the same thing, but Angular really shines when used as a SPA. That's when things will make sense. I didn't blade except for initializing my SPA after I really got into Angular. – Michael J. Calkins Dec 30 '13 at 19:37

1 Answers1

1

Two Things

I think the problem boils down to just syntax of your code.

  1. Move the ng-controller off the <form> and add it to the div that has ng-app="formApp" (not entirely sure why this works)
  2. Remove the <a> tags surrounding your checkboxes.

Seeing Live Data

Now if you add this to the bottom of your HTML:

<pre>{{ formData }}</pre>

You should be able to see the data change immediately as you change the form.

For example, when I tested I got:

{"test_message":"test","items":{"4":true,"5":true,"6":true}}

Future Stuff

For the future, you'd probably want to move the Blade stuff out of there and pull all the data with $http. This just ensures that in the future if you come back to look at the code, you know 100% that it all came from your JS code.

sevilayha
  • 111
  • 1
  • 2
  • 8
  • Hmmm... worked like a charm. Funny, because originally I had the ng-controller up in that div like you recommended. Awesome. Thanks for such a quick response! Awesome articles by the way. You guys are seriously hitting the exact topics that I am interested in. Thanks again. – Erik Aybar Dec 30 '13 at 20:03