mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
DatePicker & Form with v-model & validation in fhcAlert
This commit is contained in:
@@ -256,6 +256,8 @@ class Student extends FHC_Controller
|
||||
|
||||
public function check()
|
||||
{
|
||||
$_POST = json_decode($this->input->raw_input_stream, true);
|
||||
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'callback_isValidDate', [
|
||||
@@ -272,7 +274,7 @@ class Student extends FHC_Controller
|
||||
$gebdatum = $this->input->post('gebdatum');
|
||||
|
||||
if (!$vorname && !$nachname && !$gebdatum) {
|
||||
return $this->outputJsonSuccess([]);
|
||||
return $this->outputJsonError(['#' => 'At least one of vorname, nachname or gebdatum must be set']);
|
||||
}
|
||||
|
||||
$this->load->model('person/Person_model', 'PersonModel');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {CoreRESTClient} from '../../../../RESTClient.js';
|
||||
import BsModal from '../../../Bootstrap/Modal.js';
|
||||
import FhcFormValidation from '../../../Form/Validation.js';
|
||||
import VueDatePicker1 from '../../../vueDatepicker.js.php';
|
||||
import VueDatePicker from '../../../vueDatepicker.js.php';
|
||||
|
||||
var _uuid = 0;
|
||||
|
||||
@@ -9,128 +9,98 @@ export default {
|
||||
components: {
|
||||
BsModal,
|
||||
FhcFormValidation,
|
||||
VueDatePicker1
|
||||
VueDatePicker
|
||||
},
|
||||
props: {
|
||||
studiengangKz: Number
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
date: null,
|
||||
geschlechter: []
|
||||
geschlechter: [],
|
||||
formData: {},
|
||||
suggestions: {},
|
||||
person: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
saveTitle() {
|
||||
if (this.person === null)
|
||||
return 'Bitte auswählen';
|
||||
if (this.person === 0)
|
||||
return 'Neue Person anlegen';
|
||||
return 'zu ' + (this.person.vorname + ' ' + this.person.nachname).trim() + ' hinzufügen';
|
||||
},
|
||||
formDataPerson() {
|
||||
if (this.person)
|
||||
return this.person;
|
||||
return this.formData;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.modal.show();
|
||||
},
|
||||
send(e) {
|
||||
this.sendForm(e.target, 'components/stv/student/check')
|
||||
reset() {
|
||||
this.formData = {};
|
||||
this.person = null;
|
||||
this.suggestions = [];
|
||||
this.$fhcAlert.resetFormValidation(this.$refs.form)
|
||||
},
|
||||
loadSuggestions() {
|
||||
if (this.person)
|
||||
return;
|
||||
// TODO(chris): load serialized
|
||||
CoreRESTClient
|
||||
.post('components/stv/student/check', {
|
||||
vorname: this.formData.vorname,
|
||||
nachname: this.formData.nachname,
|
||||
gebdatum: this.formData.gebdatum
|
||||
})
|
||||
.then(result => CoreRESTClient.getData(result.data) || [])
|
||||
.then(result => {
|
||||
console.log('check: ', result);
|
||||
this.suggestions = result;
|
||||
})
|
||||
.catch(() => {
|
||||
// NOTE(chris): repeat request
|
||||
window.setTimeout(this.loadSuggestions, 100);
|
||||
});
|
||||
},
|
||||
sendForm(form, url) {
|
||||
this.resetFormValidation(form);
|
||||
const data = new FormData(form);
|
||||
return CoreRESTClient
|
||||
.post(url, data)
|
||||
send(e) {
|
||||
if (e.person === null)
|
||||
this.$fhcAlert.alertError('Select a person first'); // TODO(chris): better error handling!
|
||||
|
||||
this.$fhcAlert.resetFormValidation(form);
|
||||
const data = {...this.formData, ...(this.person || {})};
|
||||
CoreRESTClient
|
||||
.post('components/stv/student/add')
|
||||
.then(result => result.data)
|
||||
.then(result => {
|
||||
if (CoreRESTClient.isError(result))
|
||||
throw new Error(CoreRESTClient.getError(result));
|
||||
return result;
|
||||
return CoreRESTClient.getData(result);
|
||||
})
|
||||
.catch(this.handleErrors(form));
|
||||
},
|
||||
resetForm() {
|
||||
const form = this.$refs.form;
|
||||
form.reset();
|
||||
this.resetFormValidation(form);
|
||||
},
|
||||
resetFormValidation(form) {
|
||||
const event = new Event('fhc-form-reset');
|
||||
form.querySelectorAll(['[data-fhc-form-validate],[data-fhc-form-error]']).forEach(el => el.dispatchEvent(event));
|
||||
/*const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
|
||||
if (alert) {
|
||||
alert.innerHTML = '';
|
||||
alert.classList.add('d-none');
|
||||
}
|
||||
form.querySelectorAll('.invalid-feedback').forEach(n => n.remove());
|
||||
form.querySelectorAll('.is-invalid').forEach(n => n.classList.remove('is-invalid'));
|
||||
form.querySelectorAll('.is-valid').forEach(n => n.classList.remove('is-valid'));*/
|
||||
},
|
||||
handleErrors(error, form) {
|
||||
if (form === undefined) {
|
||||
if (error && error.nodeType === Node.ELEMENT_NODE)
|
||||
return err => this.handleErrors(err, error);
|
||||
} else {
|
||||
if (error?.response?.status == 400) {
|
||||
let errors = CoreRESTClient.getError(error.response.data);
|
||||
if (typeof errors !== "object")
|
||||
errors = error.response.data;
|
||||
|
||||
// NOTE(chris): reset form validation
|
||||
this.resetFormValidation(form);
|
||||
|
||||
// NOTE(chris): set form input validation
|
||||
const notFound = Object.entries(errors).filter(([key, detail]) => {
|
||||
const input = form.querySelector('[data-fhc-form-validate="' + key + '"]');
|
||||
if (!input)
|
||||
return true;
|
||||
|
||||
input.dispatchEvent(new CustomEvent('fhc-form-invalidate', {detail}));
|
||||
|
||||
/*const input = form.querySelector('[name="' + key + '"]');
|
||||
if (!input)
|
||||
return true;
|
||||
input.classList.add('is-invalid');
|
||||
const feedback = document.createElement('div');
|
||||
feedback.classList.add('invalid-feedback');
|
||||
feedback.innerHTML = detail;
|
||||
input.after(feedback);*/
|
||||
return false;
|
||||
}).map(arr => arr[1]);
|
||||
|
||||
|
||||
//const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
|
||||
const alert = form.querySelector('[data-fhc-form-error]');
|
||||
if (alert && notFound.length) {
|
||||
alert.dispatchEvent(new CustomEvent('fhc-form-error', {detail: notFound}));
|
||||
/*notFound.forEach(txt => {
|
||||
const p = document.createElement('p');
|
||||
p.innerHTML = txt;
|
||||
alert.append(p);
|
||||
});
|
||||
|
||||
if (notFound.length) {
|
||||
alert.lastChild.classList.add('mb-0');
|
||||
alert.classList.remove('d-none');
|
||||
}*/
|
||||
} else {
|
||||
notFound.forEach(this.$fhcAlert.alertError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
},test() {console.log('test')}
|
||||
.then(result => {
|
||||
this.$fhcAlert.alertSuccess('Gespeichert');
|
||||
console.log('saved');
|
||||
// TODO(chris): close
|
||||
})
|
||||
.catch(this.$fhcAlert.handleFormValidation);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.uuid = _uuid++;
|
||||
// TODO(chris): geschlechter in parent?
|
||||
CoreRESTClient
|
||||
.get('components/stv/Student/getGeschlechter')
|
||||
.then(result => CoreRESTClient.getData(result.data))
|
||||
.then(result => {
|
||||
this.geschlechter = result.data;
|
||||
this.geschlechter = result;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(CoreRestClient.getError(err.response.data) || err.message);
|
||||
});
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
template: `
|
||||
<form ref="form" class="stv-list-new" @submit.prevent="send">
|
||||
<bs-modal ref="modal" dialog-class="modal-fullscreen" @hidden-bs-modal="resetForm">
|
||||
<bs-modal ref="modal" dialog-class="modal-fullscreen" @hidden-bs-modal="reset">
|
||||
<template #title>
|
||||
InteressentIn anlegen
|
||||
</template>
|
||||
@@ -140,19 +110,19 @@ export default {
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-anrede-' + uuid">Anrede</label>
|
||||
<fhc-form-validation name="anrede">
|
||||
<input :id="'stv-list-new-anrede-' + uuid" type="text" name="anrede" class="form-control">
|
||||
<input :id="'stv-list-new-anrede-' + uuid" type="text" name="anrede" v-model="formDataPerson['anrede']" class="form-control" :disabled="person">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-titelpre-' + uuid">Titel (Pre)</label>
|
||||
<fhc-form-validation name="titelpre">
|
||||
<input :id="'stv-list-new-titelpre-' + uuid" type="text" name="titelpre" class="form-control">
|
||||
<input :id="'stv-list-new-titelpre-' + uuid" type="text" name="titelpre" v-model="formDataPerson['titelpre']" class="form-control" :disabled="person">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-titelpost-' + uuid">Titel (Post)</label>
|
||||
<fhc-form-validation name="titelpost">
|
||||
<input :id="'stv-list-new-titelpost-' + uuid" type="text" name="titelpost" class="form-control">
|
||||
<input :id="'stv-list-new-titelpost-' + uuid" type="text" name="titelpost" v-model="formDataPerson['titelpost']" class="form-control" :disabled="person">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
</div>
|
||||
@@ -160,19 +130,19 @@ export default {
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-nachname-' + uuid">Nachname*</label>
|
||||
<fhc-form-validation name="nachname">
|
||||
<input :id="'stv-list-new-nachname-' + uuid" type="text" name="nachname" class="form-control">
|
||||
<input :id="'stv-list-new-nachname-' + uuid" type="text" name="nachname" v-model="formDataPerson['nachname']" class="form-control" :disabled="person" @input="loadSuggestions">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-vorname-' + uuid">Vorname</label>
|
||||
<fhc-form-validation name="vorname">
|
||||
<input :id="'stv-list-new-vorname-' + uuid" type="text" name="vorname" class="form-control">
|
||||
<input :id="'stv-list-new-vorname-' + uuid" type="text" name="vorname" v-model="formDataPerson['vorname']" class="form-control" :disabled="person" @input="loadSuggestions">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-vornamen-' + uuid">Weitere Vornamen</label>
|
||||
<fhc-form-validation name="vornamen">
|
||||
<input :id="'stv-list-new-vornamen-' + uuid" type="text" name="vornamen" class="form-control">
|
||||
<input :id="'stv-list-new-vornamen-' + uuid" type="text" name="vornamen" v-model="formDataPerson['vornamen']" class="form-control" :disabled="person">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
</div>
|
||||
@@ -180,7 +150,7 @@ export default {
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-wahlname-' + uuid">Wahlname</label>
|
||||
<fhc-form-validation name="wahlname">
|
||||
<input :id="'stv-list-new-wahlname-' + uuid" type="text" name="wahlname" class="form-control">
|
||||
<input :id="'stv-list-new-wahlname-' + uuid" type="text" name="wahlname" v-model="formDataPerson['wahlname']" class="form-control" :disabled="person">
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,7 +158,7 @@ export default {
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'stv-list-new-geschlecht-' + uuid">Geschlecht*</label>
|
||||
<fhc-form-validation name="geschlecht">
|
||||
<select :id="'stv-list-new-geschlecht-' + uuid" class="form-control" name="geschlecht">
|
||||
<select :id="'stv-list-new-geschlecht-' + uuid" class="form-control" :disabled="person" name="geschlecht" v-model="formDataPerson['geschlecht']">
|
||||
<option v-for="geschlecht in geschlechter" :key="geschlecht.geschlecht" :value="geschlecht.geschlecht">{{geschlecht.bezeichnung}}</option>
|
||||
</select>
|
||||
</fhc-form-validation>
|
||||
@@ -196,13 +166,23 @@ export default {
|
||||
<div class="col-sm-4 mb-3">
|
||||
<label :for="'dp-input-stv-list-new-gebdatum-' + uuid">Geburtsdatum</label>
|
||||
<fhc-form-validation name="gebdatum">
|
||||
<vue-date-picker1 :uid="'stv-list-new-gebdatum-' + uuid" name="gebdatum" text-input auto-apply no-today v-model="date" :enable-time-picker="false" format="dd.MM.yyyy"></vue-date-picker1>
|
||||
<vue-date-picker :uid="'stv-list-new-gebdatum-' + uuid" name="gebdatum" text-input auto-apply no-today v-model="formDataPerson['gebdatum']" :enable-time-picker="false" format="dd.MM.yyyy" @update:model-value="loadSuggestions" :disabled="person"></vue-date-picker>
|
||||
</fhc-form-validation>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button type="submit" class="btn btn-primary">Vorschläge laden</button>
|
||||
<div class="btn-group dropup">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" style="border-bottom-right-radius: 0; border-top-right-radius: 0" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="visually-hidden">Choose Person</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<!-- TODO(chris): more details -->
|
||||
<li v-for="suggestion in suggestions" :key="suggestion.person_id"><a class="dropdown-item" :class="{active: person?.person_id == suggestion.person_id}" href="#" @click.prevent="person=suggestion">{{suggestion.vorname + ' ' + suggestion.nachname}}</a></li>
|
||||
<li><a class="dropdown-item" :class="{active: person === 0}" href="#" @click.prevent="person=0">Neue Person anlegen</a></li>
|
||||
</ul>
|
||||
<button type="submit" class="btn btn-primary" :disabled="person === null">{{saveTitle}}</button>
|
||||
</div>
|
||||
</template>
|
||||
</bs-modal>
|
||||
</form>`
|
||||
|
||||
@@ -300,6 +300,73 @@ export default {
|
||||
|
||||
// Fallback
|
||||
fhcerror.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method);
|
||||
},
|
||||
resetFormValidation(form) {
|
||||
const event = new Event('fhc-form-reset');
|
||||
form.querySelectorAll(['[data-fhc-form-validate],[data-fhc-form-error]']).forEach(el => el.dispatchEvent(event));
|
||||
/*const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
|
||||
if (alert) {
|
||||
alert.innerHTML = '';
|
||||
alert.classList.add('d-none');
|
||||
}
|
||||
form.querySelectorAll('.invalid-feedback').forEach(n => n.remove());
|
||||
form.querySelectorAll('.is-invalid').forEach(n => n.classList.remove('is-invalid'));
|
||||
form.querySelectorAll('.is-valid').forEach(n => n.classList.remove('is-valid'));*/
|
||||
},
|
||||
handleFormValidation(error, form) {
|
||||
if (form === undefined) {
|
||||
if (error && error.nodeType === Node.ELEMENT_NODE)
|
||||
return err => $fhcAlert.handleFormValidation(err, error);
|
||||
} else {
|
||||
if (error?.response?.status == 400) {
|
||||
let errors = CoreRESTClient.getError(error.response.data);
|
||||
if (typeof errors !== "object")
|
||||
errors = error.response.data;
|
||||
|
||||
// NOTE(chris): reset form validation
|
||||
$fhcAlert.resetFormValidation(form);
|
||||
|
||||
// NOTE(chris): set form input validation
|
||||
const notFound = Object.entries(errors).filter(([key, detail]) => {
|
||||
const input = form.querySelector('[data-fhc-form-validate="' + key + '"]');
|
||||
if (!input)
|
||||
return true;
|
||||
|
||||
input.dispatchEvent(new CustomEvent('fhc-form-invalidate', {detail}));
|
||||
|
||||
/*const input = form.querySelector('[name="' + key + '"]');
|
||||
if (!input)
|
||||
return true;
|
||||
input.classList.add('is-invalid');
|
||||
const feedback = document.createElement('div');
|
||||
feedback.classList.add('invalid-feedback');
|
||||
feedback.innerHTML = detail;
|
||||
input.after(feedback);*/
|
||||
return false;
|
||||
}).map(arr => arr[1]);
|
||||
|
||||
|
||||
//const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
|
||||
const alert = form.querySelector('[data-fhc-form-error]');
|
||||
if (alert && notFound.length) {
|
||||
alert.dispatchEvent(new CustomEvent('fhc-form-error', {detail: notFound}));
|
||||
/*notFound.forEach(txt => {
|
||||
const p = document.createElement('p');
|
||||
p.innerHTML = txt;
|
||||
alert.append(p);
|
||||
});
|
||||
|
||||
if (notFound.length) {
|
||||
alert.lastChild.classList.add('mb-0');
|
||||
alert.classList.remove('d-none');
|
||||
}*/
|
||||
} else {
|
||||
notFound.forEach($fhcAlert.alertError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
$fhcAlert.handleSystemError(error);
|
||||
}
|
||||
};
|
||||
app.config.globalProperties.$fhcAlert = $fhcAlert;
|
||||
|
||||
Reference in New Issue
Block a user