9b16c296f358f4b73674959befcf45981dd40ee7
[aai/sparky-fe.git] / src / generic-components / input / validation / ValidationForm.jsx
1 /*
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI service)
4  * ============================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=====================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25
26 /**
27         * ValidationForm should be used in order to have a form that handles it's
28         * internal validation state. All ValidationInputs inside the form are checked
29         * for validity and the styling and submit buttons are updated accordingly.
30         *
31         * The properties that ahould be given to the form:
32         * labledButtons - whether or not use icons only as the form default buttons or
33         * use buttons with labels onSubmit - function for click on the submit button
34         * onReset - function for click on the reset button
35         */
36 import React from 'react';
37 import ValidationButtons from './ValidationButtons.jsx';
38
39 class ValidationForm extends React.Component {
40                 
41                 static childContextTypes = {
42                                 validationParent: React.PropTypes.any,
43                                 isReadOnlyMode: React.PropTypes.bool
44                 };
45                 
46                 static defaultProps = {
47                                 hasButtons: true,
48                                 onSubmit: null,
49                                 onReset: null,
50                                 labledButtons: true,
51                                 onValidChange: null,
52                                 isValid: true
53                 };
54                 
55                 static propTypes = {
56                                 isValid: React.PropTypes.bool,
57                                 hasButtons: React.PropTypes.bool,
58                                 onSubmit: React.PropTypes.func,
59                                 onReset: React.PropTypes.func,
60                                 labledButtons: React.PropTypes.bool,
61                                 onValidChange: React.PropTypes.func
62                 };
63                 
64                 state = {
65                                 isValid: this.props.isValid
66                 };
67                 
68                 constructor(props) {
69                                 super(props);
70                                 this.validationComponents = [];
71                 }
72                 
73                 render() {
74                                 var buttons = (this.props.hasButtons) ?
75                                               <ValidationButtons labledButtons={this.props.labledButtons}
76                                                                  ref='buttons'
77                                                                  isReadOnlyMode={this.props.isReadOnlyMode}/>
78                                                 : null;
79                                 return (
80                                                 <form {...this.props} onSubmit={event => this.handleFormSubmit(event)}>
81                                                                 <div className='validation-form-content'>{this.props.children}</div>
82                                                                 {buttons}
83                                                 </form>
84                                 );
85                 }
86                 
87                 handleFormSubmit(event) {
88                                 event.preventDefault();
89                                 let isFormValid = true;
90                                 this.validationComponents.forEach(validationComponent => {
91                                                 const isInputValid = validationComponent.validate().isValid;
92                                                 isFormValid = isInputValid && isFormValid;
93                                 });
94                                 if (isFormValid && this.props.onSubmit) {
95                                                 this.props.onSubmit(event);
96                                 } else if (!isFormValid) {
97                                                 this.setState({isValid: false});
98                                 }
99                 };
100                 
101                 componentDidUpdate(prevProps, prevState) {
102                                 // only handling this programatically if the validation of the form is done
103                                 // outside of the view (example with a form that is dependent on the state
104                                 // of other forms)
105                                 if (prevProps.isValid !== this.props.isValid) {
106                                                 if (this.props.hasButtons) {
107                                                                 this.refs.buttons.setState({isValid: this.state.isValid});
108                                                 }
109                                 } else if (this.state.isValid !== prevState.isValid) {
110                                                 if (this.props.hasButtons) {
111                                                                 this.refs.buttons.setState({isValid: this.state.isValid});
112                                                 }
113                                                 // callback in case form is part of bigger picture in view
114                                                 if (this.props.onValidChange) {
115                                                                 this.props.onValidChange(this.state.isValid);
116                                                 }
117                                 }
118                 }
119                 
120                 componentDidMount() {
121                                 if (this.props.hasButtons) {
122                                                 this.refs.buttons.setState({isValid: this.state.isValid});
123                                 }
124                 }
125                 
126                 
127                 getChildContext() {
128                                 return {
129                                                 validationParent: this,
130                                                 isReadOnlyMode: this.props.isReadOnlyMode
131                                 };
132                 }
133                 
134                 
135                 /***
136                         * Used by ValidationInput in order to let the (parent) form know
137                         * the valid state. If there is a change in the state of the form,
138                         * the buttons will be updated.
139                         *
140                         * @param validationComponent
141                         * @param isValid
142                         */
143                 childValidStateChanged(validationComponent, isValid) {
144                                 if (isValid !== this.state.isValid) {
145                                                 let oldState = this.state.isValid;
146                                                 let newState = isValid &&
147                                                                 this.validationComponents.filter(
148                                                                                 otherValidationComponent => validationComponent !==
149                                                                                 otherValidationComponent).every(otherValidationComponent => {
150                                                                                 return otherValidationComponent.isValid();
151                                                                 });
152                                                 
153                                                 if (oldState !== newState) {
154                                                                 this.setState({isValid: newState});
155                                                 }
156                                 }
157                 }
158                 
159                 register(validationComponent) {
160                                 this.validationComponents.push(validationComponent);
161                 }
162                 
163                 unregister(validationComponent) {
164                                 this.childValidStateChanged(validationComponent, true);
165                                 this.validationComponents =
166                                                 this.validationComponents.filter(
167                                                                 otherValidationComponent => validationComponent !==
168                                                                 otherValidationComponent);
169                 }
170 }
171
172
173 export default ValidationForm;