对于一个小型Angular.js测试平台项目,我设置了以下代码:
My Plunked Plunker
最初,当calendarViewModel
直接包含在Angular控制器中时,我具有该测试平台的本地版本。
appControllers.controller('PageController', [
'$scope', '$http', 'Enums', 'ViewModels',
function ($scope, $http, Enums, ViewModels) {
var calendarViewModel = function () {
var pub = {};
pub.date = new Date();
pub.isOpen = false;
pub.today = function () {
if(pub.isOpen)
pub.date = new Date();
};
pub.clear = function () {
if(pub.isOpen)
pub.date = null;
};
pub.hide = function () {
pub.isOpen = false;
};
pub.toggle = function ($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.hideCalendars();
pub.isOpen = !pub.isOpen;
};
return pub;
};
// Backing model for this 'controller'
$scope.viewModel = {
// Properties:
startCalendar: new calendarViewModel(),
endCalendar: new calendarViewModel(),
// data:
// Generates an object that is sent to the server with $http calls.
data: function () {
var object = {
startDate: startCalendar.date.toString(),
endDate: endCalendar.date.toString()
};
return JSON.stringify(object);
}
};
// - Controller-specific functions... ----------------------------------
$scope.hideCalendars = function () {
$scope.viewModel.startCalendar.hide();
$scope.viewModel.endCalendar.hide();
};
$scope.clear = function () {
$scope.viewModel.startCalendar.clear();
$scope.viewModel.endCalendar.clear();
};
$scope.today = function () {
$scope.viewModel.startCalendar.today();
$scope.viewModel.endCalendar.today();
};
// Restricts certain days from being selected.
$scope.disableWeekends = function (date, mode) {
return mode === 'day'
&& (date.getDay() === Enums.DaysOfTheWeek.Sunday
|| date.getDay() === Enums.DaysOfTheWeek.Saturday);
};
// This is a demonstration scope action. Pretty much, the pattern
// I found, is to have a view model expose a method that creates
// a stringified JSON blob that we can send to the server. This
// method is how such a save function would work.
$scope.save = function () {
var promise = $http({
method: 'POST',
url: '/some/server/url',
data: $scope.viewModel.data()
});
promise.success(function (data) {
// Do something with the returned data?
}).error(function (data) {
// Do something with the error data?
});
};
// - End of Controller-specific functions... ---------------------------
// Picker-specific options...
$scope.dateOptions = {
'starting-day': Enums.DaysOfTheWeek.Monday,
'format-day': 'dd',
'format-month': 'MM',
'format-year': 'yyyy',
'min-mode': Enums.PickerMode.Day,
'max-mode': Enums.PickerMode.Year
};
$scope.format = 'MM/dd/yyyy';
$scope.today();
}
]);
但是,由于我将其重构为
ViewModels
常量对象,因此我从Angular中收到以下错误:TypeError: undefined is not a function
at Object.pub.toggle (http://run.plnkr.co/AKUBdEb5M3KT5DM9/app.services.js:31:4)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:10185:21
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:17835:17
at Scope.$eval (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:11936:28)
at Scope.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:12036:23)
at HTMLInputElement.<anonymous> (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:17834:21)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:2613:10
at forEach (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js:310:20)
之所以这样做,是因为从理论上讲,多个控制器可能需要绑定到
calendarViewModels
的日历(这就是为什么我首先创建calendarViewModel
功能对象的原因。)我想要calendarViewModel
构造而不是绑定到特定的控制器,但是,通过这种方式对其进行重构显然已经破坏了它。我认为我走在正确的道路上,但是无论如何,显然缺少某些东西。我的问题:对我来说,重构我的
calendarViewModel
的正确方法是什么,它可以工作并且更易于重用? 最佳答案
因此,您的小伙子们有几件事:
不要使用app.constant做工厂。请改用app.factory,例如:
_
appServices.factory('ViewModels', function() {
var pub = {};
pub.date = new Date();
pub.isOpen = false;
pub.today = function () {
if(pub.isOpen)
pub.date = new Date();
};
pub.clear = function () {
if(pub.isOpen)
pub.date = null;
};
pub.hide = function () {
pub.isOpen = false;
};
pub.toggle = function ($event) {
$event.preventDefault();
$event.stopPropagation();
//hideAll();
pub.isOpen = !pub.isOpen;
};
return pub;
});
执行以下操作时,将自动在控制器之间共享工厂:
_
appControllers.controller('FirstController', [ '$scope', 'MyCalendarService', function($scope, MyCalendarService){
$scope.myCalendarService = MyCalendarService;
}]);
appControllers.controller('SecondController', [ '$scope', 'MyCalendarService', function($scope, MyCalendarService){
$scope.myCalendarService = MyCalendarService;
}]);
...如果控制器在html中并行定义。如果它们是嵌套的,则只需要在顶层注入服务即可。理想情况下,您只需要在控制器中添加几个服务并将它们分配给作用域即可。
这是否回答你的问题?
PS:
hideAll
在您的插件中没有定义,我注释掉了它,事情开始起作用。编辑:此编辑的plnkr应该执行您想要的操作:http://plnkr.co/edit/7VDYDQhK2CDGnwa8qhWf?p=preview
关于javascript - 如何重构CalendarViewModel使其不绑定(bind)到特定 Controller ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25000886/