Angular Binding Whazzit ...

textbox in template not bound to data model

by gary_stenstrom

HTML

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<script src="http://metroui.org.ua/js/metro.min.js?_=1414077722981"></script>
<div data-ng-controller="pageOneFormCtrl as page">
    
    <p> The 'ProductName' text box in the 'Directive' fieldset and the textbox and label in the 'Controls' fieldset should all be in sync. </p>
    
    <fieldset><legend>Directive</legend>
    <label>Product Name</label>
    <input  type="text" id="txProductName" 
            data-ng-model="page.data.productName"
            data-metro-input-transform=""
            placeholder="product name" />
    </fieldset>
    <p>&nbsp;</p>
    
    <fieldset><legend>Controls</legend>
        As long as this is working we  know that the model is successfully being bound to the pageOneFormCtrl scope
    <p><input type="text" ng-model="page.data.productName" /></p>
        <p>-- {{ page.data.productName }} --</p>
    </fieldset>
</div>

CSS

.btn-clear{ height: 20px; width: 20px; }
.btn-clear:before { content: 'X' }

JavaScript

(function(){
    
//
// service
var productFormServices = angular.module('productFormServices', []);
    productFormServices.service('productFormService', function () {
        var self      = this;
            self.data = {
            productName: 'Initial Value'
        };
    });

//
// directive
var metroDirectives = angular.module('metroDirectives', []);
    metroDirectives.directive('metroInputTransform', function () {
        
        
        function preLink($scope, element, attrs, controller) {
            console.log("PreLink");
        };
        
        function postLink($scope, element, attrs, controller) {
            console.log("PostLink");
            
            element.bind("change", function(e) {
                $scope.$apply(function() {
                    $scope[attrs.ngModel] = e.val;
                });
            });
        };
        
        return {
            priority: 100,
            terminal: true,  // if I didn't put this here everything would execute twice
            compile: function (element, attrs) {  
                console.log("compile");
                //
                // inputTransform() modifies the DOM creating a DIV tag that wraps 
                // the original INPUT element that the directive was applied to. As 
                // well as adding a button that clears the value of the INPUT element. 
                // It replaces the original INPUT element with the following HTML ... 
                /*
                <div class="input-control text ng-pristine ng-valid">
                    <input type="text" id="txProductName" 
                           data-ng-model="$parent.page.data.productName" 
                           data-metro-input-transform="" 
                           placeholder="product name" 
                           class="ng-pristine ng-valid">
                    <button class="btn-clear" tabindex="-1" type="button"></button>
                </div>
                */
            ...