背景:在此示例中,john papa使用Object.defineProperty(vm, 'canSave', {get: canSave});
作为禁用和启用按钮的方法。我没有经过测试,但我认为这种禁用会在交易成功之前发生。
问题:为什么他在Object.defineProperty
上使用vm
初始化canSave
属性?此外,我怎样才能或何时应该在我未来的工作中使用这种做法?
控制器:
(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>
答案 0 :(得分:0)
John Papa正在使用它来演示您可以直接向viewmodel添加属性,这不是必需的或必需的。它可以像一个功能一样容易地完成。它是一个抽象层,使html中的代码更容易阅读。
最终,它只是html中绑定语法的差异。因此,而不是使数据-ng-disabled =&#34; {{vm.canSave()}}&#34;你可以简单地使用data-ng-disabled =&#34;!vm.canSave&#34;让模型担心实现细节。