Created
April 16, 2020 17:08
-
-
Save embarq/9e8221a1a8091de8765f9f63b7882cc0 to your computer and use it in GitHub Desktop.
Forms
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>DOM task: Form model</title> | |
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> | |
<style> | |
.app-container { | |
width: 420px; | |
padding-top: 3rem; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container app-container"> | |
<form action=""> | |
<p class="form-group px-3"> | |
<label for="email-control">Email</label> | |
<input id="email-control" type="email" placeholder="[email protected]" class="form-control" /> | |
</p> | |
<p class="form-group px-3"> | |
<label for="username-control">Username</label> | |
<input type="text" id="username-control" class="form-control" /> | |
</p> | |
</form> | |
</div> | |
<script src="main.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class EventEmitter { | |
constructor() { | |
this.handlers = []; | |
} | |
subscribe(eventHandler) { | |
this.handlers.push(eventHandler); | |
} | |
emit(data) { | |
this.handlers.forEach(handler => handler(data)); | |
} | |
} | |
class Validator { | |
validate() { | |
throw new Error('Not implemented'); | |
} | |
} | |
class RequiredValidator extends Validator { | |
validate(value) { | |
return value != null && (typeof value === 'string' && value.trim().length > 0); | |
} | |
} | |
class MinLengthValidator extends Validator { | |
constructor(minValue) { | |
super(); | |
if (!Number.isFinite(minValue)) { | |
throw new Error('minValue is required argument'); | |
} | |
this.minValue = minValue; | |
} | |
validate(value) { | |
return value.length > this.minValue; | |
} | |
} | |
class FormControl { | |
constructor(id, initialValue = '', validators) { | |
this.value = initialValue; | |
this.validators = validators; | |
this.status = false; | |
this.statusChange = new EventEmitter(); | |
// TODO: show hints about validation state | |
const inputElem = document.getElementById(id); | |
inputElem.addEventListener('change', (event) => { | |
this.status = this.validators.every(validator => { | |
if (!(validator instanceof Validator)) { | |
throw new Error('Invalid validator'); | |
} | |
return validator.validate(event.target.value); | |
}); | |
this.statusChange.emit(this.status); | |
}); | |
this.statusChange.subscribe(status => { | |
if (status === false) { | |
const hintElem = document.createElement('p'); | |
hintElem.className = 'text-danger'; | |
hintElem.innerText = 'Value is invalid'; | |
hintElem.id = 'hint-for-' + inputElem.id; | |
inputElem.parentElement.appendChild(hintElem); | |
inputElem.classList.toggle('is-invalid'); | |
} else { | |
const hintElem = inputElem.parentElement.querySelector('#hint-for-' + inputElem.id); | |
if (hintElem != null) { | |
inputElem.classList.toggle('is-invalid'); | |
hintElem.remove(); | |
} | |
} | |
}); | |
} | |
} | |
class FormGroup { | |
constructor(id, controls) { | |
this.status = false; | |
this.statusChange = new EventEmitter(); | |
this.controlsStatus = { }; | |
for (let control of controls) { | |
control.statusChange.subscribe(status => { | |
this.controlsStatus[control.id] = status; | |
this.status = Object.values(this.controlsStatus).every(controlStatus => (controlStatus === true)); | |
this.statusChange.emit(this.status); | |
}); | |
} | |
} | |
} | |
window.addEventListener('DOMContentLoaded', () => { | |
const registerForm = new FormGroup('', [ | |
new FormControl('email-control', '', [ | |
new RequiredValidator() | |
]), | |
new FormControl('username-control', '', [ | |
new RequiredValidator(), | |
new MinLengthValidator(3) | |
]) | |
]); | |
registerForm.statusChange.subscribe((formStatus) => { | |
console.log('Register form status is', formStatus); | |
}); | |
// const emailControl = new FormControl('email-control', '', [ | |
// new RequiredValidator() | |
// ]); | |
// const usernameControl = new FormControl('username-control', '', [ | |
// new RequiredValidator(), | |
// new MinLengthValidator(3) | |
// ]); | |
// emailControl.statusChange.subscribe(status => { | |
// console.log('Email control status is', status); | |
// }); | |
// usernameControl.statusChange.subscribe(status => { | |
// console.log('Username control status is', status); | |
// }); | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment