<!DOCTYPE html>
<html>

  <head>
    <!-- Bootstrap v2 -->
    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
    <link href="https://cdn.rawgit.com/breeze.js.labs/master/breeze.directives.css" rel="stylesheet" >
    <link href="style.css" rel="stylesheet" >
  </head>

  <body data-ng-app="app" 
        data-ng-controller="personEditController as vm" >

    <div class="container-fluid" >
    
      <h1>Breeze/Angular Validation</h1>
      <p class="notWorking" data-ng-hide="vm.isWorking" >
          This sample is broken if this text remains visible; please report it to <a href="mailto:breeze@ideablade.com">breeze@ideablade.com</a>
      </p>
      
      <div>
        <button class="btn btn-info"
            data-ng-click="vm.refresh()">
            <i class="icon-refresh icon-white"></i> refresh</button>
        <button class="btn btn-info"
            data-ng-click="vm.newPerson()">
            <i class="icon-plus icon-white"></i> new</button>
      </div>

      <input data-ng-model="vm.person.firstName" data-z-validate placeholder="First name" autofocus><br/>
      <input data-ng-model="vm.person.lastName"  data-z-validate placeholder="Last name"><br/>
      <input data-ng-model="vm.person.phone"     data-z-validate placeholder="Phone"><br/>
      <input data-ng-model="vm.person.email"     data-z-validate placeholder="Email address"><br/>
      <input data-ng-model="vm.person.blog"      data-z-validate placeholder="Blog"><br/>
      <input data-ng-model="vm.person.twitter"   data-z-validate placeholder="Twitter"><br/>
    </div> <!-- /container -->
    
    <footer>
    <p>See <a href="http://breeze.github.io/doc-breeze-labs/directives-validation.html" target="_blank">Breeze Labs: validation directive</a> for discussion.<br/>
       Copyright 2014 &copy; IdeaBlade, Inc.</p>
    </footer>
 
    <!-- 3rd party libraries -->
    <script data-require="angular.js@*" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script>
    <script src="https://cdn.rawgit.com/Breeze/breeze.js/master/build/breeze.debug.js"></script>
    <script src="https://cdn.rawgit.com/Breeze/breeze.js.labs/master/breeze.angular.js"></script>
    
    <!-- Breeze Labs: angular validation directive -->
    <script src="https://cdn.rawgit.com/Breeze/breeze.js.labs/master/breeze.directives.js"></script>

    <!-- application scripts -->
    <script src="app.js"></script>
    <script src="datacontext.js"></script>
    <script src="model.js"></script>
    <script src="personEditController.js"></script>
  </body>

</html>
input {
    border: 1px solid #ccc;
    font-family: "Segoe UI", Arial, Helvetica, sans-serif;
    padding: 0.5em;
    margin-top: 0.5em;
    width: 300px;
}

.notWorking {
  color: red;
  font-style: italic;
}

.ngCloak {
  display: none;
}
body {
    -webkit-font-smoothing: antialiased;
}

input ~ .icon-asterisk-invalid {
    top: 0.2em; /* adjust position of 'required' asterisk */
}

footer {
    margin-top: 1em;
    color: gray;
}
(function () {
    'use strict';
    
    angular.module('app').factory('model', model);

    function model(zDirectivesConfig) {
        // aliases
        var DT = breeze.DataType; 
        var Validator = breeze.Validator;
        
        return {
            configureMetadataStore: configureMetadataStore
        };
        
        function configureMetadataStore(metadataStore) {
          createTwitterValidator();
          addPersonType(metadataStore);
        }
        
        function addPersonType(metadataStore) {
          metadataStore.addEntityType({
              shortName: "Person",
              namespace: "Demo",
              autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity,
              dataProperties: {
                  id:         { dataType: DT.Int32, isPartOfKey: true },
                  firstName:  { dataType: DT.String, 
                                validators:[
                                  Validator.required(), 
                                  Validator.maxLength({maxLength: 20})] },
                  lastName:   { dataType: DT.String, 
                                validators:[
                                  Validator.required(), 
                                  Validator.maxLength({maxLength: 30})] },
                  phone:      { dataType: DT.String, 
                                validators:[
                                  Validator.phone(), 
                                  Validator.maxLength({maxLength: 30})] },
                  email:      { dataType: DT.String, 
                                validators:[
                                  Validator.emailAddress(), 
                                  Validator.maxLength({maxLength: 100})] },
                  blog:       { dataType: DT.String, 
                                validators:[
                                  Validator.url(), 
                                  Validator.maxLength({maxLength: 100})] },
                  twitter:    { dataType: DT.String, 
                                validators:[
                                  Validator.twitter(), 
                                  Validator.maxLength({maxLength: 20})] },
              }
          });
        }

        function createTwitterValidator() {
          // create the validator
          var val = Validator.makeRegExpValidator(
              'twitter',
              /^@([a-zA-Z]+)([a-zA-Z0-9_]+)$/,
              "Invalid Twitter user name: '%value%'");
              
          // register it with the Validator class
          Validator.register(val);
          
          // make it available as a Validator static fn like the others
          Validator.twitter = function() {return val;}

        }
    }
})();
(function() {
  'use strict';
  
  angular.module('app', ['breeze.directives', 'breeze.angular'])
    .config(['zDirectivesConfigProvider', configDirective]);


  //Configure the Breeze Validation Directive for bootstrap 2
  function configDirective(cfg) {
    // Custom template with warning icon before the error message
    cfg.zValidateTemplate =
       '<span class="invalid"><i class="icon-warning-sign icon-white"></i>' +
       '%error%</span>';
  }

})();
(function() {
    'use strict';
    
    angular.module('app').factory('datacontext', ['breeze', 'model', datacontext]);

    function datacontext(breeze, model) {

        var dataService = new breeze.DataService({
            serviceName: 'demo',
            hasServerMetadata: false
        });
        
        var store = new breeze.MetadataStore();
        model.configureMetadataStore(store);

        var manager = new breeze.EntityManager({
            dataService: dataService,
            metadataStore: store
        });

        var service = {
            getPersonById: getPersonById,
            newPerson: newPerson
        };
        
        return service;
        
        function getPersonById(id){
          // fake an existing person in cache
          return manager.createEntity('Person',
          
            {id: id,
             firstName: "Tracy", 
             lastName: "Nobody",
             phone: "510-555-1212",
             email: "tnobody@nobody.com",
             blog: "http://NobodyKnows.TheTroubleIveSeen.com",
             twitter: "@aintnobody"},
             
            breeze.EntityState.Unchanged); // loaded 'Unchanged' as if queried
        }
        
        function newPerson(initialValues){
          return manager.createEntity('Person', initialValues)
        }
    }
})();
(function() {
    'use strict';

    angular.module('app')
        .controller('personEditController', ['datacontext', controller]);
 
    function controller(datacontext) {

      var person42 = datacontext.getPersonById(42);

      // ViewModel API
      var vm = this;
      vm.person = person42;
      vm.newPerson = newPerson;     
      vm.refresh = refresh;
      vm.isWorking = true;

      function newPerson(){
        undo();
        vm.person = datacontext.newPerson();
      }

      function refresh(){
        undo();
        vm.person = person42;
      }

      // undo pending changes to current person
      function undo(){
        vm.person.entityAspect.rejectChanges();
      }
    }
  
})();