嵌套控制器和指令

时间:2016-09-03 12:32:40

标签: javascript angularjs

我正在努力为以下场景定义一个好的方法:

我有一个使用Laravel内置api的AngularJs应用程序。

我的任务索引页面列出了任务。在列表的底部是一个新的输入行,可以输入任务的两个基本要求,并创建一个新任务(通过调用我的API的服务),并将项目推入范围。

复杂性来自此处 - 当用户点击现有任务时,会打开侧边栏,其中会显示任务的所有详细信息。所有细节都是可编辑的,包括添加子任务,附件等。他们需要点击保存来调用API更新方法,但由于任务在列表中更新,因为他们在侧边栏中进行了更改,人们正在考虑它已经储蓄了。我想以某种方式将任务列表的范围与任务侧栏分开 - 但显然在保存任务时更新列表。

我的TasksController看起来很不整洁。目前,我有一个ng-click功能,可以创建一个“选择任务”'变量(使用所选任务),然后由侧边栏视图使用。

我知道会有更好的方法。我尝试使用指令为任务侧栏创建一个新的控制器 - 但我很难看到如何来回传递数据。

一些代码可以帮助我们了解我的来源:

app.js路线

.state('root.tasks', {
    url: '/tasks',
    views: {
        'content@root': {
            templateUrl: '../partials/tasks-index.html',
            controller: 'TasksController as TasksCtrl'
        },
        'task-detail-sidebar@root.tasks': {
            templateUrl: '../partials/task-detail-sidebar.html'
        }
    }
})

TasksController显示任务功能

vm.showTask = function(task, added) {
// if same task is clicked in list again, or close button clicked, close task
if (vm.selectedTask.id == task.id && vm.clickedShut == false && !added) {
    vm.clickedShut = true;
} else {
    // else open task sidebar and create selectedTask
    vm.clickedShut = false;
    task.newSubtask = {'title':'', 'assignees':[task.task_owner]};
    vm.selectedTask = task;

    // need to grab current owner/assignees so we know if they change when saving - if so, notifications are sent
    vm.currentOwner = task.task_owner.id;
    vm.currentAssignees = [];
    if (task.assignees) {
        for (var i = 0; i < task.assignees.length; i++) {
            vm.currentAssignees.push(task.assignees[i].id);
        }
    }
}

};

TasksController updateTask

vm.updateTaskFromSidebar = function() {
    TasksService.update(vm.selectedTask).then(function(data) {
       if (data.data.task_owner.id !== vm.currentOwner && data.data.task_owner.id !== $rootScope.currentUser.id) {
           NotificationsService.updateOwner(data.data, $rootScope.currentUser)
       }
        var newAssignees = data.data.assignees;
        var alertAssignees = [];
        if (newAssignees) {
           for (var i = 0; i < newAssignees.length; i++) {
               if (vm.currentAssignees.indexOf(newAssignees[i].id) === -1 && newAssignees[i].id !== data.data.task_owner.id && newAssignees[i].id !== $rootScope.currentUser.id) {
                   alertAssignees.push(newAssignees[i]);
               }
           }
           if (alertAssignees.length) {
               NotificationsService.updateAssignees(data.data, alertAssignees, $rootScope.currentUser);
           }
       }
        vm.showSimpleToast('Task Saved');
    }).catch(function() {
        vm.showAlertDialog('Error Updating Task', "We've spotted this and will work to resolve the problem as soon as possible.");
    });
};

2 个答案:

答案 0 :(得分:1)

您可以使用JSON.parse(JSON.stringify(task))在侧栏中克隆任务对象,并将克隆的对象放在侧栏的范围内。这在边栏控制器中发生一次,所有输入都应更新克隆对象。

当用户单击“保存”时,您将复制回已更改的实际任务键。例如,您可以使用extend。实际的保存可以在侧边栏控制器中完成,也可以在rootScope上发出事件并在任务控制器中监听事件。

答案 1 :(得分:1)

我将完成@Nitzo的答案,而不是使用事件,你应该为你的任务创建一个服务。

当用户单击某个任务时,您应该克隆它(您可以使用angular.copy()或JSON方法)并将克隆的任务和原始任务保存在服务中。

当用户保存任务时,您将获得克隆任务(用户已更改/更新)并将其与原始对象合并(您可以使用angular.extend())。

由于它是一项服务,您可以在所有控制器之间共享它,没有任何问题。您可以使用代码段作为指南=)。 (我仍然有很多提高我的角度技能,如果你发现很难找到我使用的模式结账这个真棒angular-styleguide,如果我错过使用的东西,请纠正我)

angular.module('main', [])
  .factory('taskService', taskService)
  .controller('TaskListController', TaskListController)
  .controller('TaskFormController', TaskFormController);

function taskService() {
	var service = {
		selectedTask: null,
		editingTask: null,
		tasks: [],
		load: load
	};

	function load() {
		service.tasks = [{name: "t1", value: 1}, {name: "t2", value: 1}]
	}

	return service;
}

TaskListController.$inject = ['taskService'];
function TaskListController(taskService) {
	var vm = this;

	vm.taskService = taskService;
	vm.editTask = editTask;
    taskService.load();

	function editTask(task) {
		taskService.selectedTask = task;
		taskService.editingTask = angular.copy(task);
	}

}

TaskFormController.$inject = ['taskService'];
function TaskFormController(taskService) {
	var vm = this;

	vm.taskService = taskService;
	vm.saveTask = saveTask;

	function saveTask() {
      if (taskService.selectedTask) {
		angular.extend(taskService.selectedTask, taskService.editingTask);
		taskService.selectedTask = null;
      } else {
        taskService.tasks.push(taskService.editingTask);
      }
      
      taskService.editingTask = null;
	}

}
.task_item {
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="main">

	<ul ng-controller="TaskListController as listCtrl">
		<li ng-repeat="task in listCtrl.taskService.tasks" 
			ng-click="listCtrl.editTask(task)" class="task_item">
			{{task.name}} - {{task.value}}
		</li>
	</ul>
	
	<form ng-controller="TaskFormController as formCtrl" ng-submit="formCtrl.saveTask()">
		<input type="text" placeholder="name" ng-model="formCtrl.taskService.editingTask.name"></input>
		<input type="number" placeholder="value"  ng-model="formCtrl.taskService.editingTask.value"></input>
		<input type="submit"></input>
	</form>

</div>