首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular-Formly:在多个指令中与多个表单交互

Angular-Formly:在多个指令中与多个表单交互
EN

Stack Overflow用户
提问于 2016-02-29 22:56:30
回答 1查看 1.2K关注 0票数 5

我正在尝试弄清楚如何在多个指令中保存和反应多个表单。

给你一个简短的概述:Screenshot of the current view

我有三个包含表单的标签和第四个包含JsTree (组)的标签。这三个选项卡中的每一个都包含一个指令,而该指令又包含一个Formly表单。选项卡由一个main指令包装,该指令包含一个footer指令,右下角有save和cancel按钮。

主指令:

代码语言:javascript
复制
/**
 * Displays the ui for editing a specific user
 */
export function UserDetailsDirective() {
	class UserDetailsDirective {

		/*@ngInject*/
		constructor(
			$stateParams,
			userService,
			formlyChangeService
		) {
			this.currentUser = this.currentUser || {};
			this.originalUser = this.originalUser || {};

			this.userForms = {
				mainData: {},
				personalData: {},
				basicSettings: {}
			};

			this.savingAllowed = true;
              
            /* Second try: Registering a callback at the change service, which will be executed on any field change in the passed form (mainData) */
            formlyChangeService.onFormChange('mainData', () => {
				console.log('test123');
				console.log('this123', this);

				console.log('this.userForms.mainData.api.isValid()', this.userForms.mainData.api.isValid());
			});


			if ($stateParams.id > 0) {
				userService.getUser($stateParams.id).then((userData) => {
					userData.Birthday = new Date(userData.Birthday);
					this.currentUser = userData;

					this.breadcrumbData = [...];
				})
			}
		}

		onSave(controller) {
			alert('on save');
			console.log('controller', controller);
		}
	}

	return {
		restrict: 'E',
		templateUrl: 'components/usermanagement/edit/user-details/user-details.directive.html',
		controller: UserDetailsDirective,
		controllerAs: 'controller',
		bindToController: true
	}
}
代码语言:javascript
复制
<breadcrumb [...]></breadcrumb>

<ul class="nav nav-tabs">
	<li class="active"><a data-toggle="tab" data-target="#mainData">Account data</a></li>
	<li><a data-toggle="tab" data-target="#personalData">Personal data</a></li>
	<li><a data-toggle="tab" data-target="#basicSettings">Settings</a></li>
	<li><a data-toggle="tab" data-target="#userGroupAssignment">Groups</a></li>
</ul>

<div class="row">
	<div class="col-lg-6">
		<div class="tab-content">
			<div id="mainData" class="tab-pane fade in active">
				<main-data user="controller.currentUser"></main-data>
			</div>
			<div id="personalData" class="tab-pane fade">
				<personal-data user="controller.currentUser"></personal-data>
			</div>
			<div id="basicSettings" class="tab-pane fade">
				<basic-settings user="controller.currentUser"></basic-settings>
			</div>
			<div id="userGroupAssignment" class="tab-pane fade">
				<group-assignment user="controller.currentUser"></group-assignment>
			</div>
		</div>
	</div>
	<div class="col-lg-6">
		[...] <!-- Right column -->
	</div>
</div>

<!-- Footer -->
<user-details-footer
	on-save="controller.onSave(controller)"
	saving-allowed="controller.savingAllowed"
></user-details-footer>

页脚指令

代码语言:javascript
复制
/**
 * Displays the user details footer
 */
export function UserDetailsFooterDirective() {
	class UserDetailsFooterDirective {

		/*@ngInject*/
		constructor(
			$state,
			Notification,
			$translate
		) {
			this.state = $state;
			this.notification = Notification;
			this.translate = $translate;

			this.savingAllowed = this.savingAllowed || false;
		}

		/**
		 * Event that is triggered on save button click
		 *
		 * Propagates to the parent controller via attribute binding
		 */
		saveEvent() {
			if (typeof this.onSave === 'function') {
				this.onSave();
			}
		}

		/**
		 * Navigates to the user list
		 */
		goToUserList() {
			this.state.go('userList');
		}
	}

	return {
		restrict: 'E',
		templateUrl: 'components/usermanagement/edit/user-details-footer/user-details-footer.directive.html',
		controller: UserDetailsFooterDirective,
		controllerAs: 'controller',
		bindToController: true,
		scope: {
			onSave: '&?',
			savingAllowed: '=?'
		}
	}
}
代码语言:javascript
复制
<nav class="navbar navbar-fixed-bottom">
	<div class="container-fluid pull-right">
		<button class="btn btn-default" ng-click="controller.goToUserList()"><i class="fontIcon fontIconX"></i> Cancel</button>
		<button class="btn btn-primary" ng-disabled="controller.savingAllowed !== true" ng-click="controller.saveEvent()"><i class="fontIcon fontIconSave"></i> Save</button>
	</div>
</nav>

第一个选项卡的指令

代码语言:javascript
复制
/**
 * Displays the contents of the tab "Account data"
 */
export function MainDataDirective() {
	class MainDataDirective {

		/*@ngInject*/
		constructor(
			formlyFormService,
			mainDataFieldProviders,
			$state,
			userSubmitService,
			$timeout,
		    formlyChangeService,
		    $scope
		) {
			this.state = $state;
			this.$timeout = $timeout;

			this.userSubmitService = userSubmitService;

			this.model = {};
			this.originalUser = this.originalUser || {};
			this.fields = [];

			this.form = null;
			var that = this;

            /* Third try: Watching the form instance => partial success */
			this.watch('formMainData', function(x, y, form) {
				console.log('formMainData', form);
				that.form = form;
				form.watch('$invalid', function(foo, bar, value) {
                    /* This will react on field changes but it seems really dirty to me */
					console.log('$invalid', arguments);
				});

			});


			formlyFormService.getFormConfiguration(mainDataFieldProviders).then((result) => {
				/* Here the formly fields are set */
                this.fields = result;
                /* Second try: A service which provides a callback that will be executed on field invalidation => no success */
				formlyChangeService.registerFields(this.fields, 'mainData');
			}, (error) => {
				console.error('getMainDataFields error:', error);
			});

			this.api = {
				isValid: angular.bind(this, this.isValid),
				submit: angular.bind(this, this.onSubmit)
			}
		}

        /* First try to get the validity of the fields => no success */
		isValid() {
			//return this.$timeout(() => {
				let isValid = true;

				this.fields.some((field) => {
					if (
						field.validation.errorExistsAndShouldBeVisible === true
						|| field.validation.serverMessages.length > 0
					) {
						isValid = false;
						return true;
					}
				});

				//return isValid;
			//}, 10);

            return isValid;
		}

		/**
		 * Method triggered by the formSubmit event
         */
		onSubmit() {
			this.userSubmitService.submitUser(this.fields, this.model);
		}
    }

	return {
		restrict: 'E',
		templateUrl: 'components/usermanagement/edit/main-data/main-data.directive.html',
		controller: MainDataDirective,
		controllerAs: 'controller',
		bindToController: true,
		scope: {
			originalUser: '=user',
			api: '=?'
		},
		link: (scope) => {
			scope.$watch('controller.originalUser', (newValue) => {
				if (newValue.hasOwnProperty('ID')) {
					scope.controller.model = angular.copy(newValue);
				}
			});
		}
	}
}
代码语言:javascript
复制
<form name="controller.form" ng-submit="controller.onSubmit()" class="form-horizontal" novalidate>
	<formly-form form="controller.formMainData" model="controller.model" fields="controller.fields" ></formly-form>
</form>

第二次尝试: FormlyChangeService =>触发了更改事件,但在验证=>之前未成功

代码语言:javascript
复制
export /*@ngInject*/ function FormlyChangeService() {
	let callbacks = [];

	return {
		triggerFormChangeEvent: triggerFormChangeEvent,
		registerFields: registerFields,
		onFormChange: onFormChange
	};

	function triggerFormChangeEvent(value, options) {
		callbacks.forEach((callback) => {
			if (
				typeof callback === 'function'
				&& callback.formDirective === options.templateOptions.formDirective
			) {
				callback();
			}
		});
	}

	function onFormChange(formDirective, callback) {
		callback.formDirective = formDirective;
		callbacks.push(callback);
	}

	function registerField(fieldConfig) {
		fieldConfig.templateOptions.changeEvents.push(
			triggerFormChangeEvent
		);
	}

	function registerFields(fieldConfigs, formDirective) {
		fieldConfigs.forEach((fieldConfig) => {
			fieldConfig.templateOptions.formDirective = formDirective;
			registerField(fieldConfig);

			fieldConfig.watcher = {
				listener: function() {
					console.log('listener', arguments);
				}
			};

			console.log('fieldConfig', fieldConfig);


			fieldConfig.watch('$valid', function() {
console.log('valid field', arguments);
			});




		});
	}

}

Formly表单提供了一个用户模型,该模型由main指令提供。

我必须同时保存所有四个选项卡,因为必须存在几个必填字段才能保存输入的记录。现在到了棘手的部分:

我想要禁用保存按钮,如果模型没有改变,或者在任何形式的任何字段中发生错误。我还想知道错误来自于哪一种形式。

我想到的是Formly字段配置中的事件或观察器或类似的东西。

我尝试了字段配置上的onChange事件,但它是在字段验证运行之前触发的,因此我无法获得该字段的当前错误状态。

错误状态必须向上传递到main指令,从那里向下传递到save按钮。

有没有人能帮我弄到表单(或者更好的是相应的字段)来告诉主指令有一个无效的字段?

举例说明如此复杂的任务真的很困难,所以如果有任何晦涩的地方,请让我知道。

非常提前感谢您。

朱利安

EN

回答 1

Stack Overflow用户

发布于 2017-02-06 17:40:16

我认为您应该有一个所有指令都依赖的服务或工厂来保存所有表单的数据。

这样,您就可以在您的指令中设置一个监视,它将调用您的共享服务上的任何方法来验证/使其他选项卡上的表单无效。

我希望这能帮到你

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35702664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档