Ben Nadel's ngModel Experiement

by nickadeemus2002

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
<div id="root" ng-app="Demo">
    <div ng-controller="AppController">
         <h1>Experimenting With ngModel And ngModelController In AngularJS</h1>

        <!-- We're using the FORM directive in this demo as the ngModel usage will automatically interact with the FormController to do things like apply an "ng-dirty" class to the form when our list-toggle directive is consumed by the user. -- NOTE: By naming the form, an instance of the FormController will automatically be applied to the current Scope using the given name (ie, $scope.myForm). -->
        <form name="myForm">
            <!-- Using this directive to iterate over the given list when clicked, one item per click. When moving onto the next item, the ngModel value is updated to reflect the current selection; this will, in turn, interact automatically with the parent Form directive. -- * bnListToggle: The expression used to access the target list. * text: The expression used to render the selected value. -->
            <div ng-model="selectedFriend" bn-list-toggle="friends" text="( id + '. ' + name )"></div>
            <p>
                <!-- Using this to alter the view-model externally to the directive. --> <a ng-click="selectFirstFriend()">Select First Friend</a>&mdash;
                <!-- Using this to erase a friend selection. --> <a ng-click="selectNullFriend()">Select NULL Friend</a>

            </p>
        </form>
    </div>
</div>

CSS

form {
    border: 1px dotted #CCCCCC;
    padding: 12px 30px 10px 30px;
    position: relative;
}
form.ng-dirty {
    border-color: #CC0000;
}
form.ng-dirty:before {
    background-color: red;
    color: #FFFFFF;
    content:"So Dirty!";
    font-family: monospace;
    font-size: 11px;
    left: 0px;
    line-height: 15px;
    padding: 3px 7px 3px 7px;
    position: absolute;
    top: 0px;
}
div[bn-list-toggle] {
    background-color: #FAFAFA;
    border: 1px solid #CCCCCC;
    border-radius: 3px 3px 3px 3px;
    cursor: pointer;
    margin: 20px 0px 20px 0px;
    padding: 20px 20px 20px 20px;
    user-select: none;
    -moz-user-select: none;
    -webkit-user-select: none;
}
div[bn-list-toggle].ng-dirty {
    border-color: #FFAAAA;
}
div[bn-list-toggle]:active {
    background-color: #F0F0F0;
}
div[bn-list-toggle] em {
    color: #AAAAAA;
}
a[ng-click] {
    color: red;
    cursor: pointer;
    text-decoration: underline;
    user-select: none;
    -moz-user-select: none;
    -webkit-user-select: none;
}

JavaScript

// Create an application module for our demo.
		var app = angular.module("Demo", []);
		// -------------------------------------------------- //
		// -------------------------------------------------- //

		// I control the root of the application.
		app.controller(
		    "AppController",

		function ($scope) {
		    // I hold the list of friends over which we will be iterating in the
		    // ngModel control.
		    $scope.friends = [{
		        id: 1,
		        name: "Kim"
		    }, {
		        id: 2,
		        name: "Sarah"
		    }, {
		        id: 3,
		        name: "Joanna"
		    }, {
		        id: 4,
		        name: "Tricia"
		    }, {
		        id: 5,
		        name: "Anna"
		    }];

		    // By default, select the first friend.
		    $scope.selectedFriend = $scope.friends[0];

		    // For debugging purposes, let's observe changes in the selected friend.
		    // This way, we can see when / how the view-model is changed by the two-way
		    // ngModel binding.
		    $scope.$watch(
		        "selectedFriend",

		    function handleModelChange(newValue, oldValue) {
		        // Ignore null values as we can't render them (using .name).
		        if (!newValue || !oldValue) {
		            return (console.info("Null value change:", newValue));
		        }
		        console.log("Selected friend changed from [", newValue.name, "-->", oldValue.name, "].");
		    });

		    // Since we are using a named-form, we now have a copy of the 
		    // FormController on the scope. As such, we can watch for changes in the
		    // form state and respond. In this case, we're logging when the form loses
		    // its pristine nature.
		    $scope.$watch(
		        "myForm.$dirty",

		    function handleModelChange(newValue) {
		        if (newValue) {
		            console.warn("Form is so dirty.");
		        }
		    });


		    // ---
		    // PUBLIC METHODS.
		    // ---


		    // I select the first friend in the list. This demonstrates that the 
		    // ngModel binding...