2016-02-29 9 views
5

Próbuję dowiedzieć się, jak zapisać i reagować na wiele formularzy w wielu dyrektywach.Kątowo - Formalnie: Interakcja z wieloma formularzami w wielu dyrektywach

Aby dać krótki przegląd: Screenshot of the current view

ja mam trzy zakładki zawierające formularze i czwarty zawierający JsTree (grupy). Każda z trzech zakładek zawiera dyrektywę, która z kolei zawiera formularz Formalny. Zakładki są zawijane przez dyrektywę główną, która zawiera dyrektywę stopki z przyciskami zapisu i anulowania w prawym dolnym rogu.

główna dyrektywy:

/** 
 
* 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>

dyrektywa stopka

/** 
 
* 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>

dyrektywa

Pierwsza zakładka jest

/** 
 
* 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>

Druga próba: FormlyChangeService => dostał wydarzenie zmiana zwolniony ale przed walidacji => bez powodzenia

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 } 
 

 
}

form Formly są karmione model użytkownika, który jest dostarczany przez dyrektywę główną.

Muszę zapisać wszystkie cztery zakładki w tym samym czasie, ponieważ istnieje kilka pól obowiązkowych, które muszą być obecne, aby zapisać wprowadzony rekord. Nadchodzi trudna część:

Chcę, aby przycisk zapisu był wyłączony, jeśli model się nie zmienił lub wystąpił błąd w dowolnym polu w dowolnej formie. Chcę również wiedzieć, z której postaci pochodzi błąd.

To, o czym myślałem, to wydarzenie lub obserwator w formularzu konfiguracji pola lub coś podobnego.

Próbowałem zdarzenia onChange w konfiguracji pola, ale jest ono uruchamiane tuż przed uruchomieniem sprawdzania poprawności pola, więc nie otrzymam bieżącego stanu błędu tego pola.

Status błędu należy przekazać do głównej dyrektywy, skąd powinien zostać przekazany do przycisku zapisu.

Czy ktoś może mi pomóc uzyskać formularze (lub jeszcze lepiej odpowiednie pola), aby powiedzieć głównej dyrektywie, że istnieje nieprawidłowe pole?

Naprawdę trudno jest zobrazować tak złożone zadanie, więc jeśli pojawi się jakaś niejasność, proszę dać mi znać.

Dziękuję bardzo z góry.

Julian

Odpowiedz

0

myślę, że należy mieć usługę lub fabrykę, że wszystkie dyrektywy zależą który przechowuje dane dla wszystkich swoich formach.

W ten sposób można skonfigurować zegarek w dyrektywie, który wywoła dowolną metodę w usłudze współdzielonej w celu sprawdzania/unieważniania formularzy na innych kartach.

Mam nadzieję, że pomoże to

Powiązane problemy