2016-02-29 12 views
5

Tôi đang cố gắng tìm ra cách lưu và phản ứng trên nhiều biểu mẫu trong nhiều chỉ thị.Góc-Formly: Tương tác với nhiều biểu mẫu trong nhiều chỉ thị

Để cung cấp cho bạn một cái nhìn tổng quan ngắn: Screenshot of the current view

Tôi đã có ba tab chứa các hình thức và một phần tư chứa một JsTree (Groups). Mỗi một trong ba tab chứa một chỉ thị, trong đó, lần lượt, chứa một biểu mẫu Formly. Các tab được bao bọc bởi chỉ thị chính chứa chỉ thị chân trang với các nút lưu và hủy ở góc dưới cùng bên phải.

chỉ thị chi tiết:

/** 
 
* Displays the ui for editing a specific user 
 
*/ 
 
export function UserDetailsDirective() { 
 
\t class UserDetailsDirective { 
 

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

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

 
\t \t \t 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',() => { 
 
\t \t \t \t console.log('test123'); 
 
\t \t \t \t console.log('this123', this); 
 

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

 

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

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

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

 
\t return { 
 
\t \t restrict: 'E', 
 
\t \t templateUrl: 'components/usermanagement/edit/user-details/user-details.directive.html', 
 
\t \t controller: UserDetailsDirective, 
 
\t \t controllerAs: 'controller', 
 
\t \t bindToController: true 
 
\t } 
 
}
<breadcrumb [...]></breadcrumb> 
 

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

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

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

Footer chỉ

/** 
 
* Displays the user details footer 
 
*/ 
 
export function UserDetailsFooterDirective() { 
 
\t class UserDetailsFooterDirective { 
 

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

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

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

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

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

chỉ

Đầu tab của

/** 
 
* Displays the contents of the tab "Account data" 
 
*/ 
 
export function MainDataDirective() { 
 
\t class MainDataDirective { 
 

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

 
\t \t \t this.userSubmitService = userSubmitService; 
 

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

 
\t \t \t this.form = null; 
 
\t \t \t var that = this; 
 

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

 
\t \t \t }); 
 

 

 
\t \t \t formlyFormService.getFormConfiguration(mainDataFieldProviders).then((result) => { 
 
\t \t \t \t /* 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 */ 
 
\t \t \t \t formlyChangeService.registerFields(this.fields, 'mainData'); 
 
\t \t \t }, (error) => { 
 
\t \t \t \t console.error('getMainDataFields error:', error); 
 
\t \t \t }); 
 

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

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

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

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

 
      return isValid; 
 
\t \t } 
 

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

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

Second try: FormlyChangeService => có sự kiện thay đổi bắn nhưng trước khi xác nhận => không thành công

export /*@ngInject*/ function FormlyChangeService() { 
 
\t let callbacks = []; 
 

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

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

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

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

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

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

 
\t \t \t console.log('fieldConfig', fieldConfig); 
 

 

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

 

 

 

 
\t \t }); 
 
\t } 
 

 
}

Các hình thức Trước đây được cho ăn với một mô hình người dùng, được cung cấp bởi chỉ thị chính.

Tôi phải lưu tất cả bốn tab cùng một lúc vì có một số trường bắt buộc phải có mặt để lưu bản ghi đã nhập. Bây giờ ở đây có phần phức tạp:

Tôi muốn nút lưu bị tắt nếu mô hình không thay đổi hoặc xảy ra lỗi ở bất kỳ trường nào dưới mọi hình thức. Tôi cũng muốn biết hình thức nào đến từ lỗi.

Điều tôi nghĩ là một sự kiện hoặc người xem trong cấu hình trường Formly hoặc nội dung tương tự.

Tôi đã thử sự kiện onChange trên cấu hình trường nhưng nó được kích hoạt ngay trước khi xác thực trường chạy, vì vậy tôi sẽ không nhận được trạng thái lỗi hiện tại của trường đó.

Trạng thái lỗi phải được chuyển đến chỉ thị chính, từ đó nó sẽ được chuyển xuống nút lưu.

Có ai có thể giúp tôi nhận các biểu mẫu (hoặc thậm chí tốt hơn các trường tương ứng) để nói với chỉ thị chính rằng có trường không hợp lệ không?

Rất khó để minh họa một tác vụ phức tạp như vậy, vì vậy nếu có bất kỳ sự tối tăm nào, vui lòng cho tôi biết.

Cảm ơn bạn rất nhiều trước.

Julian

Trả lời

0

Tôi nghĩ bạn nên có một dịch vụ hoặc nhà máy mà tất cả chỉ thị của bạn phụ thuộc vào dữ liệu chứa tất cả biểu mẫu của bạn.

Bằng cách này, bạn có thể thiết lập đồng hồ trong chỉ thị sẽ gọi bất kỳ phương thức nào trên dịch vụ được chia sẻ của bạn để xác thực/hủy biểu mẫu trên các tab khác của bạn.

Tôi hy vọng điều này sẽ giúp

Các vấn đề liên quan