2015-08-13 3 views
0

Arrière-plan: Dans cet exemple, john papa utilise Object.defineProperty(vm, 'canSave', {get: canSave}); pour désactiver et activer un bouton. Je n'ai pas testé mais je suppose que cette désactivation se produit jusqu'au succès de la transaction.Pourquoi John Papa utilise Object.defineProperty par rapport à l'initialisation normale?

Question: Pourquoi-t-il utiliser Object.defineProperty sur vm pour initialiser la propriété canSave? De plus, comment puis-je, ou quand devrais-je, utiliser cette pratique dans mon propre travail futur?

Controller:

(function() { 
    'use strict'; 

    angular 
     .module('app.speaker') 
     .controller('SpeakerDetail', SpeakerDetail); 

    SpeakerDetail.$inject = [ 
     '$location', '$scope', '$routeParams', '$window', 
     'common', 'config', 'datacontext', 'model' 
    ]; 

    function SpeakerDetail(
     $location, $scope, $routeParams, $window, 
     common, config, datacontext, model) { 
     /*jshint validthis: true */ 
     var vm = this; 
     var entityName = model.entityNames.speaker; 
     var logger = common.logger; 
     var $q = common.$q; 
     var wipEntityKey; 

     vm.cancel = cancel; 
     vm.goBack = goBack; 
     vm.hasChanges = false; 
     vm.isSaving = false; 
     vm.save = save; 
     vm.speaker = null; 
     vm.speakers = []; 

     Object.defineProperty(vm, 'canSave', {get: canSave}); 

     activate(); 

     function activate() { 
      onDestroy(); 
      onHasChanges(); 
//   TODO: Using a resolver on all routes or datacontext.ready in every controller 
//   return datacontext.ready([getRequestedSpeaker()]).then(onEveryChange); 
      return getRequestedSpeaker().then(onEveryChange); 
     } 

     function autoStoreWip(immediate) { 
      common.debouncedThrottle('speakerdetail', storeWipEntity, 1000, immediate); 
     } 

     function cancel() { 
      datacontext.cancel(); 
      removeWipEntity(); 
      common.replaceLocationUrlGuidWithId(vm.speaker.id); 
      if (vm.speaker.entityAspect.entityState.isDetached()) { 
       gotoSpeakers(); 
      } 
     } 

     function canSave() { 
      return vm.hasChanges && !vm.isSaving; 
     } 

     function getRequestedSpeaker() { 
      var val = $routeParams.id; 
      if (val === 'new') { 
       vm.speaker = datacontext.speaker.create(); 
       return vm.speaker; 
      } 

      return datacontext.speaker.getEntityByIdOrFromWip(val) 
       .then(function(data) { 
        if (data) { 
         // data is either an entity or an {entity, wipKey} pair 
         wipEntityKey = data.key; 
         vm.speaker = data.entity || data; 
        } else { 
         logger.warning('Could not find session id = ' + val); 
         gotoSpeakers(); 
        } 
       }) 
       .catch(function(error) { 
        logger.error('Error while getting speaker id = ' + val + '; ' + error); 
        gotoSpeakers(); 
       }); 
     } 

     function goBack() { 
      $window.history.back(); 
     } 

     function gotoSpeakers() { 
      $location.path('/speakers'); 
     } 

     function onDestroy() { 
      $scope.$on('$destroy', function() { 
       autoStoreWip(true); 
       datacontext.cancel(); 
      }); 
     } 

     function onEveryChange() { 
      $scope.$on(config.events.entitiesChanged, function(event, data) { 
       autoStoreWip(); 
      }); 
     } 

     function onHasChanges() { 
      $scope.$on(config.events.hasChangesChanged, 
       function(event, data) { 
        vm.hasChanges = data.hasChanges; 
       }); 
     } 

     function removeWipEntity() { 
      datacontext.zStorageWip.removeWipEntity(wipEntityKey); 
     } 

     function save() { 
      if (!canSave()) { 
       return $q.when(null); 
      } // Must return a promise 

      vm.isSaving = true; 
      return datacontext.save().then(function(saveResult) { 
       vm.isSaving = false; 
       removeWipEntity(); 
       common.replaceLocationUrlGuidWithId(vm.speaker.id); 
      }).catch(function(error) { 
       vm.isSaving = false; 
      }); 
     } 

     function storeWipEntity() { 
      if (!vm.speaker) { 
       return; 
      } 
      var description = (vm.speaker.fullName || '[New speaker]') + ' ' + vm.speaker.id; 
      var routeState = 'speaker'; 
      wipEntityKey = datacontext.zStorageWip.storeWipEntity(
       vm.speaker, wipEntityKey, entityName, description, routeState); 
     } 
    } 
})(); 

HTML:

<section id="speaker-view" class="mainbar" 
     data-ng-controller="SpeakerDetail as vm"> 
    <section class="matter"> 
     <div class="container"> 
      <div> 
       <button class="btn btn-info btn-form-md" 
         data-ng-click="vm.goBack()"> 
        <i class="fa fa-hand-o-left"></i>Back 
       </button> 
       <button class="btn btn-info btn-form-md" 
         data-ng-click="vm.cancel()" data-ng-disabled="!vm.canSave"> 
        <i class="fa fa-undo"></i>Cancel 
       </button> 
       <button class="btn btn-info btn-form-md" 
         data-ng-click="vm.save()" data-ng-disabled="!vm.canSave"> 
        <i class="fa fa-save"></i>Save 
       </button> 

       <!--Need ng-hide for show/hide animations--> 
       <span data-ng-show="vm.hasChanges" class="dissolve-animation ng-hide flag-haschanges"> 
        <i class="fa fa-asterisk fa fa-asterisk-large" rel="tooltip" title="You have changes"></i> 
       </span> 
      </div> 
      <div class="widget wgreen"> 
       <div data-cc-widget-header title="Edit {{vm.speaker.fullName || 'New Speaker'}}"></div> 
       <div class="widget-content user"> 
        <div class="form-group"> 
         <label class="control-label">First Name</label> 

         <div> 
          <input class="form-control" 
            data-ng-model="vm.speaker.firstName" 
            data-z-validate 
            placeholder="First Name"/> 
         </div> 
        </div> 
        <div class="form-group"> 
         <label class="control-label">Last Name</label> 

         <div> 
          <input class="form-control" 
            data-ng-model="vm.speaker.lastName" 
            data-z-validate 
            placeholder="Last Name"/> 
         </div> 
        </div> 
        <div class="form-group"> 
         <label class="control-label">Email</label> 

         <div> 
          <input class="form-control" 
            data-ng-model="vm.speaker.email" 
            data-z-validate 
            placeholder="Email"/> 
         </div> 
        </div> 
        <div class="form-group"> 
         <label class="control-label">Blog</label> 

         <div> 
          <input class="form-control" 
            data-ng-model="vm.speaker.blog" 
            data-z-validate 
            placeholder="Blog"/> 
         </div> 
        </div> 
        <div class="form-group"> 
         <label class="control-label">Twitter</label> 

         <div> 
          <input class="form-control" 
            data-ng-model="vm.speaker.twitter" 
            data-z-validate 
            placeholder="Twitter"/> 
         </div> 
        </div> 
        <div class="form-group"> 
         <img data-cc-img-person="{{vm.speaker.imageSource}}" class="img-thumbnail"/> 
        </div> 
        <div class="form-group"> 
         <label class="control-label">Bio</label> 

         <div> 
          <textarea class="form-control" 
             data-ng-model="vm.speaker.bio" 
             data-z-validate 
             placeholder="Enter speaker bio"></textarea> 
         </div> 
        </div> 
       </div> 
      </div> 
     </div> 
    </section> 
</section> 
+2

Vous ne pouvez pas manipuler cette propriété accidentellement. Ce n'est pas accessible en écriture, configurable ou énumérable. – Teemu

+0

par exemple, il empêche les utilisateurs de le changer à partir des outils de chrome? c'est ça que tu veux dire? –

+0

Il écrit dans vm.isSaving = true; à l'intérieur enregistrer()? Est-ce que ça n'écrit pas? –

Répondre

0

John Papa l'utilise démontrer que vous pouvez ajouter des propriétés directement à la viewmodel, ce ne est pas nécessaire ou obligatoire. Cela aurait pu être fait aussi facilement en tant que fonction. C'est une couche d'abstraction pour rendre le code dans le HTML plus facile à lire.

En fin de compte, il s'agit juste d'une différence de syntaxe pour la liaison dans le code HTML. Donc, plutôt que d'avoir data-ng-disabled = "{{vm.canSave()}", vous pouvez simplement utiliser data-ng-disabled = "! Vm.canSave" et laisser le modèle s'inquiéter des détails de l'implémentation.