As you can see below, I have a modal that should be validated then send a request to the server. The problem is that if I try to submit for the first time, that validation is worked properly but for the second time it won't work. When I debug the codes I found out that validationCheck() worked fine but the resolve() doesn't return any result to the add() in certificate-manager file.
request.js
let insert = function (isPost = false, url, data, reloadLocation = false, table = null,
modal = null, ponds) {
let request = null;
if (isPost) {
let uploadNotify = uploadNotification();
//step 3
let config = {
onUploadProgress: function (progressEvent) {
let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(percentCompleted);
uploadNotify.update('message', '<strong>Uploading</strong> ' + percentCompleted + ' %');
uploadNotify.update('progress', percentCompleted);
},
headers: {
'content-type': 'multipart/form-data'
}
};
//step 4
request = axios.post(url, data, config)
} else {
//step 4
request = axios.get(url, {
params: data
});
}
request.then(function (response) {
console.log(response);
let data = response['data'];
if (data['status'] === 200) {
let content = {
'title': 'Done!',
'message': data['message']
};
notification(content, 1);
if (reloadLocation)
location.reload();
if (table) {
table.ajax.reload();
clearModal('.inp', ponds);
}
}
})
.catch(function (error) {
console.log(error);
let data = error['data'];
let content = {
'title': 'Error!',
'message': data['message']
};
notification(content, 0);
})
.then(function () {
if (modal)
closeModal(modal);
});
};
utilities.js
async function validationCheck (id, rules) {
jQuery.validator.addMethod('passwordCheck', function (value, element, param) {
//Your Validation Here
let oldPass = jQuery('#input-old-password').val();
let confirmPass = jQuery('#input-confirm-password').val();
return oldPass != null && confirmPass === value;
// return bool here if valid or not.
}, 'Your error message!');
jQuery.validator.addMethod('phoneNumber', function (value, element, param) {
value = value.replace(/\s+/g, "");
return this.optional(element) || value.length > 9 &&
value.match(/\(?([0-9]{3})\)?([ .-]?)([0-9]{3})\2([0-9]{4})/);
}, 'Please specify a valid phone number');
jQuery.validator.addMethod('startDate', function (value, element, param) {
return (parseInt(value) > 2000)
}, 'Please specify a valid year');
jQuery.validator.addMethod('endDate', function (value, element, param) {
return (parseInt(value) >= parseInt(jQuery('#input-start-time').val()) ||
jQuery('#input-current').is(":checked"))
}, 'Please specify a valid year');
jQuery.validator.addMethod('uendDate', function (value, element, param) {
return (parseInt(value) >= parseInt(jQuery('#input-update-start-time').val()) ||
jQuery('#input-update-current').is(":checked"))
}, 'Please specify a valid year');
return new Promise((resolve, reject)=> {
jQuery(id).validate({
// define validation rules
rules: rules,
errorPlacement: function (error, element) {
let group = element.closest('.input-group');
if (group.length) {
group.after(error.addClass('invalid-feedback'));
} else {
element.after(error.addClass('invalid-feedback'));
}
},
// messages: {
// username: {
// required: "Username is required"
// }
// },
//display error alert on form submit
invalidHandler: function (event, validator) {
// let alert = jQuery('#kt_form_1_msg');
// alert.removeClass('kt--hide').show();
KTUtil.scrollTo(id, -200);
reject(false);
},
submitHandler: function (form) {
resolve(true);
//form[0].submit(); // submit the form
}
});
});
}
certificate-manager.js
let add = async function () {
let check = await validationCheck("#form", {
title: {
required: true
},
company: {
required: true
},
start: {
required: true,
date: true,
digits: true,
minlength: 4,
maxlength: 4,
startDate: true
},
end: {
date: true,
digits: true,
minlength: 4,
maxlength: 4,
endDate: true
},
description: {
required: true
}
}).then(value => {
console.log(value)
insert(
false,
'/api/add/certificate',
getInputsData(),
false,
table,
"#kt_modal")
}, reason => {
console.log(reason)
}).catch(reason => {
console.log(reason)
});
}
<!--begin:: insert Modal-->
<div class="modal fade" id="kt_modal" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New Certificate</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
</button>
</div>
<div class="modal-body">
<form id="form">
<div class="row">
<div class="col-12">
<div class="form-group">
<label for="input-title"
class="form-control-label">Title</label>
<input type="text" class="inp form-control"
name="title"
id="input-title">
</div>
<div class="form-group">
<label for="input-company-institute"
class="form-control-label">Company/Institute</label>
<input type="text" class="inp form-control" name="company" id="input-company-institute">
</div>
<div class="row">
<div class="form-group col-6">
<label for="input-start-time"
class="form-control-label">From Year</label>
<input type="text" class="inp form-control" name="start" id="input-start-time">
</div>
<div class="form-group col-6">
<label for="input-end-time"
class="form-control-label">To Year</label>
<input type="text" class="inp form-control" name="end" id="input-end-time">
<div class="mt-2">
<label for="input-current" class="kt-checkbox kt-checkbox--brand col-6">
<input type="checkbox" id="input-current"> Current
<span></span>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="input-description"
class="form-control-label">Description</label>
<textarea class="inp form-control" name = "description" id="input-description"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button id="add-btn" onclick="add()" type="submit" class="btn btn-primary" >Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!--end::insert Modal-->
the order of the files is:
'../../../assets/adminPanel/js/utilities.js',
'../../../assets/adminPanel/js/request.js',
'../../../assets/adminPanel/js/pages/resume/certificate-manager.js'
Related
I have made and AngularJs app and made Form in HTML/CSS. The form takes 2 Dates. StartDate and endDate. For validations, I used the AngularJs Ng-messages. I created a custom validation function to check that endDate should not be before startDate. But the function is not invoking. Things i have checked.
Include Ng-messages file in start.
Add the function to Scope.
add the customer function name in input Tag of HTML.
Checked the spelling issue.
But nothing has worked for me. So, here I am to show it to you guys.
Layout = null;
}
<form name="newTenatForm" class="flex-fill" ng-submit="newTenatForm.$valid && onAddEditTenantSubmitForm(newTenatForm)" novalidate>
<div class="row">
<div class="col-lg-6 offset-lg-3">
<div class="card mb-0">
<div class="card-body">
<div class="text-center mb-3">
<i class="icon-stack icon-2x text-success border-success border-3 rounded-round p-3 mb-3 mt-1"></i>
<h5 class="mb-0">#ViewBag.title</h5>
<span class="d-block text-muted">Fields with * are required</span>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group form-group-feedback form-group-feedback-right">
<input type="text" class="form-control" placeholder="Name *" name="tenantName" ng-minlength="5" ng-model="state.tenantModel.name" required>
<ng-messages class="form-text text-danger-400"
ng-if="newTenatForm.$submitted || newTenatForm.tenantName.$touched"
for="newTenatForm.tenantName.$error">
<div ng-message="minlength">Tenant name is too short.</div>
<div ng-message="required">Tenant name is required</div>
</ng-messages>
<div class="form-control-feedback">
<i class="icon-user-check text-muted"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group form-group-feedback form-group-feedback-right">
<input type="text" class="form-control" placeholder="Identifier *" name="tenantIdentifier" ng-minlength="5" ng-model="state.tenantModel.identifier" required>
<ng-messages class="form-text text-danger-400"
ng-if="newTenatForm.$submitted || newTenatForm.tenantIdentifier.$touched"
for="newTenatForm.tenantIdentifier.$error">
<div ng-message="minlength">Tenant Identifier is too short.</div>
<div ng-message="required">Tenant identifier is required</div>
</ng-messages>
<div class="form-control-feedback">
<i class="icon-user-check text-muted"></i>
</div>
</div>
</div>
</div>
<div class="form-group form-group-feedback form-group-feedback-right">
<input type="text" class="form-control" placeholder="Connection String" ng-model="state.tenantModel.connectionString">
<div class="form-control-feedback">
<i class="icon-user-plus text-muted"></i>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group form-group-feedback form-group-feedback-right">
<input type="date" class="form-control" placeholder="Start Date" id="anytime-date" name="tenantStartDate" ng-model="state.tenantModel.startFrom" required>
<ng-messages class="form-text text-danger-400"
ng-if="newTenatForm.$submitted || newTenatForm.tenantStartDate.$touched"
for="newTenatForm.tenantStartDate.$error">
<div ng-message="required">Tenant start date is required</div>
</ng-messages>
<div class="form-control-feedback">
<i class="icon-user-lock text-muted"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group form-group-feedback form-group-feedback-right">
<input type="date" class="form-control" placeholder="End Date" id="tenantEndDate" name="tenantEndDate" ng-model="state.tenantModel.endOn" required compareWithStartDate>
<ng-messages class="form-text text-danger-400"
ng-if="newTenatForm.$submitted || newTenatForm.tenantEndDate.$touched"
for="newTenatForm.tenantEndDate.$error">
<div ng-message="required">Tenant end date is required</div>
<div ng-message="checkEndDate">End date cannot be before start date.</div>
</ng-messages>
<div class="form-control-feedback">
<i class="icon-user-lock text-muted"></i>
</div>
</div>
</div>
</div>
<div class="form-group form-group-feedback form-group-feedback-right">
<div class="form-group row">
<label class="col-form-label col-lg-2">Tenant Type *</label>
<div class="col-lg-10">
<select class="form-control" id="tenantType" name="tenantType" ng-model="state.tenantModel.tenantType" required>
<option value="1">Trial</option>
<option value="2">Standard</option>
</select>
<ng-messages class="form-text text-danger-400"
ng-if="newTenatForm.$submitted || newTenatForm.tenantType.$touched"
for="newTenatForm.tenantType.$error">
<div ng-message="required">Pleas select tenant type.</div>
</ng-messages>
</div>
</div>
</div>
<button type="submit" value="Submit" class="btn bg-teal-400 btn-labeled btn-labeled-right"><b><i class="icon-plus3"></i></b> #if (ViewBag.title == "Update Tenant")
{<span>Update Acccount</span> }
else
{ <span>Create account </span>} </button>
</div>
</div>
</div>
</div>
</form>```
and this is Js code.
```(function () {
var app = angular.module('app');
app.controller('MultiTenantController', ['$scope', '$window', '$filter', 'TenantServices', function ($scope, $window, $filter, TenantServices) {
var objectA = {}
var state = {
tenantModel: {
addedOn: '',
connectionString: '',
createdBy: '',
endOn: '',
id: '',
identifier: '',
isDisabled: '',
items: [{
isDisabled: '',
tenantType: '',
endOn: '',
startFrom: '',
}],
name: '',
startFrom: '',
tenantType: '',
userId: '',
},
};
var init = function (id) {
if (id) { tenantEdit(id); };
$(document).ready(function () {
tenantTable = $('#table_Tenants').DataTable({
ajax: {
url: 'API/MultiTenant/Pagged',
method: 'POST'
},
columns: [
{ data: 'name' },
{ data: 'identifier' },
{ data: 'connectionString' },
{
data: 'startFrom',
render: function (startFrom) {
return $filter('date')(startFrom, 'medium');
}
},
{
data: 'addedOn',
render: function (addedOn) {
return $filter('date')(addedOn, 'medium');
}
},
{
data: 'endOn',
render: function (endOn) {
return $filter('date')(endOn, 'medium');
}
},
{
data: 'isDisabled',
render: function (isDisabled) {
return !isDisabled ?'<span class="badge badge-success">Active</span>':'<span class="badge badge-danger">Inactive</span>';
}
},
{
data: function (data) {
return data;
},
orderable: false,
render: function (data) {
return `<div class="list-icons">
<div class="dropdown">
<a href="#" class="list-icons-item" data-toggle="dropdown">
<i class="icon-menu9"></i>
</a>
<div class="dropdown-menu dropdown-menu-right">
<i class="icon-database-upload"></i>Create Database
<i class="icon-database-edit2"></i>Edit
<i class="icon-database-remove"></i>Delete
</div>
</div>
</div>`;
}
},
]
});
tenantTable.on('click', '.createTenantDatabase', function () {
const $row = $(this).closest('tr');
const rowData = tenantTable.row($row).data();
addTenantDatabase(rowData);
});
tenantTable.on('click', '.deleteTenant', function () {
const $row = $(this).closest('tr');
const rowData = tenantTable.row($row).data();
deleteTenant(rowData);
});
})
};
const onAddEditTenantSubmitForm = function (newTenatForm) {
if (!state.tenantModel.userId) {
addTenant(newTenatForm);
}
else {
updateTenant(newTenatForm);
}
};
var addTenant = function (newTenatForm) {
state.isLoading = true;
TenantServices.addTenant(state.tenantModel).then(
function () {
swalInit.fire({
title: 'Success',
text: 'Tenant has been created',
type: 'success'
});
},
function (errorResponse) {
if (errorResponse.status === 400) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while adding tenant.',
type: 'error 400'
});
}
else if (errorResponse.status === 500) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while adding tenant.',
type: 'error 500'
});
}
}
)
.finally(() => state.isLoading = false);
};
var addTenantDatabase = function (rowObj) {
state.isLoading = true;
TenantServices.createTenantDatabase(rowObj.i).then(
function () {
swalInit.fire({
title: 'Success',
text: 'Tenant Database has been created',
type: 'success'
});
table_Tenants.ajax.reload();
},
function (errorResponse) {
if (errorResponse.status === 400) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while creating database tenant.',
type: 'error 400'
});
}
else if (errorResponse.status === 500) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while creating database tenant.',
type: 'error 500'
});
}
}
)
.finally(() => state.isLoading = false);
};
var updateTenant = function (rowObj) {
state.isLoading = true;
TenantServices.updateTenant(state.tenantModel).then(
function () {
swalInit.fire({
title: 'Success',
text: 'Tenant Updated!',
type: 'success'
});
tenantTable.ajax.reload();
},
function (errorResponse) {
if (errorResponse.status === 500) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while Updating Tenant.',
type: 'error'
});
}
else if (errorResponse.status === 404) {
swalInit.fire({
title: 'Server Error',
text: 'Tenant not found on Server.',
type: 'error'
});
}
}
)
.finally(() => state.isLoading = false);
};
var deleteTenant = function (rowObj) {
state.isLoading = true;
TenantServices.deleteTenant(rowObj.id).then(
function () {
swalInit.fire({
title: 'Success',
text: 'Tenant Deleted!',
type: 'success'
});
tenantTable.ajax.reload();
},
function (errorResponse) {
if (errorResponse.status === 500) {
swalInit.fire({
title: 'Server Error',
text: 'An server error occurred while Deleting Tenant.',
type: 'error'
});
}
else if (errorResponse.status === 404) {
swalInit.fire({
title: 'Server Error',
text: 'Tenant not found on Server.',
type: 'error'
});
}
}
)
.finally(() => state.isLoading = false);
};
var tenantEdit = function (id) {
TenantServices.getTenantById(id).then(function (data) {
var startDate = new Date(data.found.startFrom + "Z");
var endDate = new Date(data.found.endOn + "Z");
state.tenantModel = data.found;
state.tenantModel.startFrom = startDate;
state.tenantModel.endOn = endDate;
if(state.tenantModel.tenantType == 1)
{
$(function () {
$('#tenantType').val('1');
});
} else if (state.tenantModel.tenantType == 2)
{
$(function () {
$('#tenantType').val('2');
});
}
});
};
var compareWithStartDate = function () {
if (state.tenantModel.startFrom == state.tenantModel.endOn) {
newTenatForm.tenantEndDate.$setValidity('checkEndDate', true);
}
else {
newTenatForm.tenantEndDate.$setValidity('checkEndDate', false);
}
};
$scope.onAddEditTenantSubmitForm = onAddEditTenantSubmitForm;
$scope.tenantEdit = tenantEdit;
$scope.compareWithStartDate = compareWithStartDate;
$scope.state = state;
$scope.init = init;
}]);
})();```
My mistake here was not making the directive for the custom validation.
I want to be displayed the toastr popup message when the user try to insert the duplicate value for BageCode in form the if anyone can help me it will be so kind of him.
I the rest form column validation is working the toaster is working but I don't know how to compare the data from database and data in form
like this
if (this.form.BadgeCode == data.BadgeCode) {
toast.fire({
type: "warning",
title: "The badge code has already been taken."
});
}
Code in EmployeeController is:
public function index()
{
$date=\Carbon\Carbon::today();
// $this->authorize('isAdmin');
$employee=Employee::where('expiredate','>',$date)->paginate(5);
// return Employee::all();
return response()->json($employee);
}
public function store(Request $request)
{
// $this->authorize('isAdmin');
$this->validate($request,[
// 'BadgeCode'=>'required|string',
'BadgeCode'=>'required|unique:employees,BadgeCode',
'BadgeType'=>'required',
]) 'company_id'=>'required',
}
Code in api route is:
Route::apiResources(['employee'=>'API\EmployeeController']);
Code in Employee.vue is:
<div
style="width:45%;margin-left: 35%;"
class="modal fade"
id="addNew"
tabindex="-1"
role="dialog"
aria-labelledby="addNewLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" v-show="!editMode" id="addNewLabel">Add New employee</h5>
<h5 class="modal-title" v-show="editMode" id="addNewLabel">Update employee's Info</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form
#submit.prevent="editMode ? updateemployee() : createemployee()"
enctype="multipart/form-data"
>
<div class="modal-body">
<div class="form-group">
<select
name="company_id"
id="company_id"
:class="{'is-invalid':form.errors.has('company_id')}"
class="form-control"
v-model="form.company_id"
>
<option value selected>Select Company</option>
<option
v-for="Company in Companies"
:key="Company.id"
:value="Company.id"
>{{Company.Company}}</option>
</select>
<has-error :form="form" field="company_id"></has-error>
</div>
<div class="form-group">
<input
v-model="form.BadgeCode"
placeholder="Enter BadgeCode"
type="text"
name="BadgeCode"
class="form-control"
/>
<!-- :class="{ 'is-invalid': form.errors.has('BadgeCode') }" -->
<!-- <has-error :form="form" field="BadgeCode"></has-error> -->
</div>
<div class="form-group">
<select
name="BadgeType"
v-model="form.BadgeType"
id="BadgeType"
class="form-control"
:class="{'is-invalid':form.errors.has('BadgeType')}"
>
<option value selected>Select BadgeType</option>
<option value="Resident">Resident</option>
<option value="Non-Resident-Expat">Non-Resident Expat</option>
<option value="Non-Resident-LN">Non-Resident LN</option>
<option value="Baron-employee">Baron-employee</option>
</select>
<has-error :form="form" field="BadgeType"></has-error>
</div>
</div>
</form>
</div>
</div>
</div>
Code in script is:
<script>
export default {
// el: "#wrapper2",
data() {
return {
seen: false,
seen2: true,
color: "blue",
size: "20px",
editMode: false,
Companies: {},
employees: {},
form: new Form({
id: "",
BadgeCode: "",
BadgeType: "",
company_id: "",
})
};
},
methods: {
getvalidateion() {
axios.get("api/employee").then(response => {
let data = response.data.data;
if (data) {
data.forEach(element => {
if (this.form.BadgeCode == data.BadgeCode) {
toast.fire({
type: "warning",
title: "The badge code has already been taken."
});
}
});
} else {
console.log("NO DATA");
}
});
},
createemployee() {
this.getvalidateion();
if (this.form.company_id == "") {
toast.fire({
type: "warning",
title: "Please Select the Company."
});
} else if (this.form.BadgeCode == "") {
toast.fire({
type: "warning",
title: "BadgeCode is required."
});
} else if (this.form.BadgeType == "") {
toast.fire({
type: "warning",
title: "Please Select the BadgeType."
});
} else if (this.form.nationality_id == "") {
toast.fire({
type: "warning",
title: "Please Select the Nationality."
});
} else if (this.form.expiredate == "" || this.form.issuedate == "") {
toast.fire({
type: "warning",
title: "Please fill the issuedate or expiredate fileds ."
});
} else if (this.form.photo.length == "") {
toast.fire({
type: "warning",
title: "Please select photo."
});
} else if (
this.form.afghanidatephoto != undefined &&
this.form.afghanidatephoto.length == ""
) {
toast.fire({
type: "warning",
title: "Please select AfghaniDate."
});
} else {
this.form
.post("api/employee")
.then(() => {
// the below function will be use to reload the page
// this.$emit("refreshPage");
$("#addNew").modal("hide");
toast.fire({
type: "success",
title: "employee Created successfully"
});
this.form.reset();
$("#afghanidatephoto").val("");
$("#photo").val("");
Fire.$emit("refreshPage");
})
.catch(e => {
console.log(e);
});
}
},
created() {
Fire.$on("searching", () => {
let query = this.$parent.search;
axios
.get("api/findemployee?q=" + query)
.then(data => {
this.employees = data.data;
})
.catch(() => {});
});
this.loademployees();
this.getvalidateion();
// load the page after 3 secound
Fire.$on("refreshPage", () => {
this.loademployees();
});
}
};
</script>
Code in Modal is:
$table->string('BadgeCode')->unique();
I found the solution instate of data.BadgeCode I should have put element.BadgeCode anyway thanks guys
getvalidateion() {
axios.get(this.url).then(response => {
let data = response.data;
//this.Companies != undefined && this.Companies.length == 0
if (data) {
data.forEach(element => {
this.employees2.push(element.BadgeCode);
if (this.form.BadgeCode == element.BadgeCode) {
toast.fire({
type: "warning",
title: "BadgeCode is already has been taken."
});
}
});
} else {
console.log("NO DATA");
}
});
}
My html code is
I also need to add sez which is in array format and also i need to add multiple images, need to provide add image and when clicking on it, need to add images as needed by the client
<form method="POST" enctype="multipart/form-data" v-on:submit.prevent="handleSubmit($event);">
<div class="row">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Name</label>
<input type="text" class="form-control" v-model="name">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Alias</label>
<input type="text" class="form-control" v-model="alias">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Sex</label>
<select class="form-control" v-model="sex" id="level">
<option value="Male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
</div>
<div class="row" v-for="(book, index) in sez" :key="index">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Date </label>
<input type="date" class="form-control" v-model="book.date">
</div>
</div>
<div class="col-md-8">
<div class="form-group label-floating">
<label class="control-label"> Details</label>
<input type="text" class="form-control" book.details>
</div>
</div>
</div>
<a #click="addNewRow">Add</a>
<div class="card-content">
<div class="row">
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Signature</span>
<label class="custom-file-upload"><input type="file" name="photo" accept="image/*" />
</label>
</div>
</div>
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Recent Photograph</span>
<label class="custom-file-upload">
<input type="file" name="sign"/>
</label>
</div>
</div>
</div>
</div>
</form>
My vue js code is
addForm = new Vue({
el: "#addForm",
data: {
name: '',
alias: '',
sex: '',
sez: [{
date: null,
details: null,
}, ],
photo: '',
sign: '',
},
methods: {
addNewRow: function() {
this.seziure.push({
date: null,
details: null,
});
},
handleSubmit: function(e) {
var vm = this;
data = {};
data['sez'] = this.sez;
data['name'] = this.name;
data['alias'] = this.alias;
data['sex'] = this.sex;
//how to add images
$.ajax({
url: 'http://localhost:4000/save/',
data: data,
type: 'POST',
dataType: 'json',
success: function(e) {
if (e.status) {
vm.response = e;
alert("success")
} else {
vm.response = e;
console.log(vm.response);
alert("Registration Failed")
}
}
});
return false;
},
},
});
This is my code. I have no idea about how to add images in this case.
Can anyone please help me pass this data.
How to pass this data along with images to the backend?
I don't want to use base64 encoding. I need to just pass this image in this ajax post request along with other data
Using axios:
Template
...
<input type="file" name="photo" accept="image/*" #change="setPhotoFiles($event.target.name, $event.target.files) />
...
Code
data () {
return {
...
photoFiles: [],
...
}
},
...
methods: {
...
setPhotoFiles (fieldName, fileList) {
this.photoFiles = fileList;
},
...
handleSubmit (e) {
const formData = new FormData();
formData.append('name', this.name);
formData.append('alias', this.alias);
formData.append('sex', this.sex);
...
this.photoFiles.forEach((element, index, array) => {
formData.append('photo-' + index, element);
});
axios.post("http://localhost:4000/save/", formData)
.then(function (result) {
console.log(result);
...
}, function (error) {
console.log(error);
...
});
}
}
I'm not sure where would you like the extra images to appear, but I added them after this column:
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Recent Photograph</span>
<label class="custom-file-upload">
<input type="file" name="sign"/>
</label>
</div>
</div>
And here's the column I added — "add images": (You can try this feature here, with the updates)
<div class="col-md-4">
<ul class="list-group" :if="images.length">
<li class="list-group-item" v-for="(f, index) in images" :key="index">
<button class="close" #click.prevent="removeImage(index, $event)">×</button>
<div class="button success expand radius">
<label class="custom-file-upload">
<input type="file" class="images[]" accept="image/*" #change="previewImage(index, $event)">
</label>
</div>
<div :class="'images[' + index + ']-preview image-preview'"></div>
</li>
</ul>
<button class="btn btn-link add-image" #click.prevent="addNewImage">Add Image</button>
</div>
And the full Vue JS code (with jQuery.ajax()):
addForm = new Vue({
el: "#addForm",
data: {
name: '',
alias: '',
sex: '',
sez: [{
date: null,
details: null
}],
// I removed `photo` and `sign` because (I think) the're not necessary.
// Add I added `images` so that we could easily add new images via Vue.
images: [],
maxImages: 5,
// Selector for the "Add Image" button. Try using (or you should use) ID
// instead; e.g. `button#add-image`. But it has to be a `button` element.
addImage: 'button.add-image'
},
methods: {
addNewRow: function() {
// I changed to `this.sez.push` because `this.seziure` is `undefined`.
this.sez.push({
date: null,
details: null
});
},
addNewImage: function(e) {
var n = this.maxImages || -1;
if (n && this.images.length < n) {
this.images.push('');
}
this.checkImages();
},
removeImage: function(index) {
this.images.splice(index, 1);
this.checkImages();
},
checkImages: function() {
var n = this.maxImages || -1;
if (n && this.images.length >= n) {
$(this.addImage, this.el).prop('disabled', true); // Disables the button.
} else {
$(this.addImage, this.el).prop('disabled', false); // Enables the button.
}
},
previewImage: function(index, e) {
var r = new FileReader(),
f = e.target.files[0];
r.addEventListener('load', function() {
$('[class~="images[' + index + ']-preview"]', this.el).html(
'<img src="' + r.result + '" class="thumbnail img-responsive">'
);
}, false);
if (f) {
r.readAsDataURL(f);
}
},
handleSubmit: function(e) {
var vm = this;
var data = new FormData(e.target);
data.append('sez', this.sez);
data.append('name', this.name);
data.append('alias', this.alias);
data.append('sex', this.sex);
// The `data` already contain the Signature and Recent Photograph images.
// Here we add the extra images as an array.
$('[class~="images[]"]', this.el).each(function(i) {
if (i > vm.maxImages - 1) {
return; // Max images reached.
}
data.append('images[' + i + ']', this.files[0]);
});
$.ajax({
url: 'http://localhost:4000/save/',
data: data,
type: 'POST',
dataType: 'json',
success: function(e) {
if (e.status) {
vm.response = e;
alert("success");
} else {
vm.response = e;
console.log(vm.response);
alert("Registration Failed");
}
},
cache: false,
contentType: false,
processData: false
});
return false;
},
},
});
Additional Notes
I know you're using Node.js in the back-end; however, I should mention that in PHP, the $_FILES variable would contain all the images (so long as the fields name are properly set); and I suppose Node.js has a similar variable or way of getting the files.
And in the following input, you may have forgotten to wrap book.details in v-model:
<input type="text" class="form-control" book.details>
<input type="text" class="form-control" v-model="book.details"> <!-- Correct -->
UPDATE
Added feature to limit number of images allowed to be selected/uploaded, and added preview for selected image. Plus the "send images as array" fix.
If you're using HTML5, try with a FormData object ; it will encode your file input content :
var myForm = document.getElementById('addForm');
formData = new FormData(myForm);
data: formData
Use below templete to show/upload the image:
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onImageUpload">
</div>
<div v-else>
<img :src="image" />
<button #click="removeImage">Remove image</button>
</div>
Js code:
data: {
image: '',
imageBuff: ''
},
methods: {
onImageUpload(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
var image = new Image();
var reader = new FileReader();
this.imageBuff = file;
reader.onload = (e) => {
this.image = e.target.result;
};
reader.readAsDataURL(file);
},
removeImage: function(e) {
this.image = '';
},
handleSubmit(e) {
const formData = new FormData();
formData.append('name', this.name);
formData.append('alias', this.alias);
formData.append('sex', this.sex);
formData.append('image', this.imageBuff);
...
// Ajax or Axios can be used
$.ajax({
url: 'http://localhost:4000/save/',
data: formData,
processData: false, // prevent jQuery from automatically transforming the data into a query string.
contentType: false,
type: 'POST',
success: function(data) {
console.log(data);
...
}
});
}
}
Now its been 46 day's till i am stuck with this. Or there is Another way to Do this.
I Know This very simple But How can i wrap input-group under form-group. I am submitting the form data in codeigniter using ajax and showing validation errors.
The issue is that input-group-addon wraps to the next line underneath the form field when the error control is added by Jquery Validate.
Controller
function infoValidation() {
$result = array('status' => false, 'message' => array());
$this->form_validation->set_error_delimiters('<div class="text-danger">','</div>');
if ($this->form_validation->run('company_registration')) {
$result['status'] = true;
}else {
foreach ($_POST as $key => $value) {
$result['message'][$key] = form_error($key);
}
}
echo json_encode($result);
}
view
<div class="col-lg-6">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">*</span>
<input type = "text" name="creditCardNumber" class="form-control input-md" id="creditCardNumber" placeholder="Mobile No">
</div>
</div>
ajax
I have also try to append the element But Nothing Happens
$.ajax({
url : me.attr('action'),
dataType : 'json',
type : 'POST',
data : me.serialize(),
success: function(resp) {
console.log(resp);
if (resp.status == true) {
$('#myModal').modal('show');
$(".form-group").removeClass('has-error').removeClass('has-success');
$(".text-danger").remove();
}else {
$('#msg').html('<div class="well"><h5>Please Check Your Details</h5></div>');
$.each(resp.message, function(key, value) {
var element = $("#"+key);
element.closest('div.form-group, div.input-group')
.addClass(value.length > 0 ? 'has-error' : 'has-success')
.find('.text-danger').remove();
element.after(value);
});
}
}
});
I think you need to override the jQuery validate plugin method in order to get compatibility with bootstrap.
Refer http://jsfiddle.net/mapb_1990/hTPY7/7/
Example code
$('form').validate({
rules: {
firstname: {
minlength: 3,
maxlength: 15,
required: true
},
lastname: {
minlength: 3,
maxlength: 15,
required: true
}
},
highlight: function(element) {
$(element).closest('.form-group').addClass('has-error');
},
unhighlight: function(element) {
$(element).closest('.form-group').removeClass('has-error');
},
errorElement: 'span',
errorClass: 'help-block',
errorPlacement: function(error, element) {
if(element.parent('.input-group').length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
});
Just add label for error at your desired location:
<label for="creditCardNumber" generated="true" class="error">
<div class="col-lg-6">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">*</span>
<input type = "text" name="creditCardNumber" class="form-control input-md" id="creditCardNumber" placeholder="Mobile No">
</div>
<label for="creditCardNumber" generated="true" class="error"></label>
</div>
I have some code that opens a modal that contains a form when a marker is placed on a layer in leaflet. It all worked well with out any issues. I copied this code so I could make a second button to control the opening of another modal containing a different form. I changed the link information but when the button is clicked the
L.DomEvent.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', L.bind(this.startCreating, this));
Opens up both forms at the same time or opens one then when closed and clicked againit will open both. Im not sure whats going on because each modal has a different ID.
Here is a live example of the map with the modals. Click the small elements/buttons on the left under the zoom control and drag the new market and click again to set its place on the map.
Leaflet Map with modals
Here is the JS code that should call the first modal called eventDataModal. The main link in the code is near the top:
L.MarkerControl = L.Control.extend({
options: {
position: 'topleft',
url: 'http://echostorm.mynetgear.com:8080/geoserver/usa/ows',
userName: 'wfspost',
password: 'createfeature'
},
map: null,
marker: null,
binded: false,
onAdd: function (map) {
this.map = map;
var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
// link = L.DomUtil.create('a', 'glyphicon glyphicon-map-marker', container);
link = L.DomUtil.create('a', 'glyphicon glyphicon-eye-open', container);
link.href = '#';
link.title = 'Create a new visual report';
link.innerHTML = '';
L.DomEvent.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', L.bind(this.startCreating, this));
map.on("editable:drawing:commit", L.bind(this.onMarkerAdd, this));
return container;
},
startCreating: function() {
this.marker = this.map.editTools.startMarker();
},
onMarkerAdd: function(e) {
this.nearestFeature = null;
this.findNearestPoints(e.layer.getLatLng());
},
onFormClosed: function() {
if (this.marker!=null) {
this.map.editTools.featuresLayer.removeLayer(this.marker);
this.marker = null;
}
},
findNearestPoints: function(latlng) {
var defaultParameters = {
service: 'WFS',
version: '1.0.0',
request: 'GetFeature',
typeName: 'usa:within5mi',
maxFeatures: 5,
outputFormat: 'text/javascript',
format_options: 'callback: nearestPoints',
srsName: 'EPSG:4326',
viewparams: 'radius:802;lon:'+latlng.lng+';lat:'+latlng.lat,
};
var parameters = L.Util.extend(defaultParameters);
$.ajax({
jsonp: false,
url: this.options.url + L.Util.getParamString(parameters),
dataType: 'jsonp',
jsonpCallback: 'nearestPoints',
success: L.bind(this.handleNearestPoints, this)
});
},
handleNearestPoints: function(data) {
this.clearModal();
this.setModalDate();
if (data && data.type=="FeatureCollection"
&& data.features && data.features.length
&& data.features.length > 0) {
this.fillModal(data.features[0]);
}
this.openPopup();
},
formatDate: function(date) {
var day = date.getDate();
return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+(day < 10 ? "0"+day : day);
},
clearModal: function() {
$('#eventDataModal').find('input').each(
function() {
$(this).val("");
}
);
$('#eventDataModal').find('textarea').each(
function() {
$(this).val("");
}
);
},
setModalDate: function() {
$("#form-patrolDate").val(this.formatDate(new Date()));
},
fillModal: function(feature) {
var props = feature.properties;
$("#form-region").val(props["Region"]);
$("#form-circuitID").val(props["Circuit_ID"]);
$("#form-circuitName").val(props["Circuit_Name"]);
$("#form-vendor").val(props["Vendor"]);
$("#form-quad").val(props["Quad"]);
},
openPopup: function() {
this.bindEvents();
$('#eventDataModal').modal('show');
},
bindEvents: function() {
if (!this.binded) {
$('#eventDataModal').on('hidden.bs.modal', L.bind(this.onFormClosed, this));
$("#saveEventDataModal").on('click', L.bind(this.onSave, this))
this.binded = true;
}
},
onSave: function() {
var properties = this.getFormData(),
request = this.wfsBody("usa", "usa:pecotest", "geom", properties);
console.log(request);
this.makeRequest(request);
},
makeRequest: function(body) {
$.ajax({
method: "POST",
crossDomain: true,
url: this.options.url,
contentType: "text/xml",
dataType: "text",
data: body,
headers: {
"Authorization": "Basic " + btoa(this.options.userName + ":" + this.options.password)
},
jsonpCallback: 'datasave',
success: L.bind(this.onDataSave, this),
failure: function(r){console.log("AJAX Failure!");console.log(r);}
});
},
onDataSave: function(data) {
console.log(data);
},
getFormData: function() {
var result = {};
$('#eventDataModal').find('input').each(
function() {
if (this.type=="checkbox") {
result[this.name] = this.checked ? "Yes" : "No";
} else {
result[this.name]=$(this).val();
}
}
);
$('#eventDataModal').find('textarea').each(
function() {
result[this.name]=$(this).val();
}
);
return result;
},
wfsBody: function(namesapce, typeName, geometryField, properties) {
var xml;
xml ='<wfs:Transaction service="WFS" version="1.0.0"';
xml += ' xmlns:wfs="http://www.opengis.net/wfs"';
xml += ' xmlns:usa="http://census.gov"';
xml += ' xmlns:gml="http://www.opengis.net/gml">\n';
xml += ' <wfs:Insert>\n';
xml += ' <'+typeName+'>\n';
xml += ' <usa:'+geometryField+'>\n';
xml += this.marker.toGML()+"\n";
xml += ' </usa:'+geometryField+'>\n';
for (var k in properties) {
if (properties.hasOwnProperty(k)) {
xml += "<"+namesapce+":"+k+">";
xml += properties[k];
xml += "</"+namesapce+":"+k+">\n";
}
}
xml += ' </'+typeName+'>\n';
xml += ' </wfs:Insert>\n';
xml += '</wfs:Transaction>\n';
return xml;
}
});
L.Marker.include({
toGML: function(){
var latlng = this.getLatLng(),
xml;
xml = '<gml:Point srsName="EPSG:4326"><gml:coordinates cs=","
decimal="." ts=" ">';
xml += latlng.lng + ',' + latlng.lat;
xml += '</gml:coordinates></gml:Point>';
return xml;
}
});
Here is the corresponding HTML for the modal evenDataModal
<div class="modal fade" id="eventDataModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-
label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Create New Visual Report</h4>
</div>
<div class="modal-body">
<form action="php\new_peco_visual_report_db_insert.php
method="POST"><div class="form-group">
<label for="form-priority">ID Code</label>
<input type="number" class="form-control" id="form-priority"
name="ID_Code" placeholder="ID_Code">
</div>
<div class="form-group">
<label for="form-region">Region</label>
<input type="text" class="form-control" id="form-region"
name="Region" placeholder="region">
</div>
<div class="form-group">
<label for="form-circuitID">Circuit ID</label>
<input type="number" class="form-control" id="form-circuitID"
name="Circuit_ID" placeholder="Circuit ID">
</div>
<div class="form-group">
<label for="form-circuitName">Circuit Name</label>
<input type="text" class="form-control" id="form-circuitName"
name="Circuit_Name" placeholder="Circuit Name">
</div>
<div class="form-group">
<label for="form-patrolDate">Patrol Date</label>
<input type="date" class="form-control" id="form-patrolDate"
name="Patrol_Date" placeholder="Patrol Date">
</div>
<div class="form-group">
<label for="form-vendor">Vendor</label>
<input type="text" class="form-control" id="form-vendor"
name="Vendor" placeholder="Vendor">
</div>
<div class="form-group">
<label for="form-repairNumber">Repair Number</label>
<input type="text" class="form-control" id="form-repairNumber"
name="Repair_Number" placeholder="Repair Number">
</div>
<div class="form-group">
<label for="form-problemDescription"> Problem
Description</label>
<input type="text" class="form-control" id="form-
problemDescription" name="Problem_Description"
placeholder="Problem
Description">
</div>
<div class="form-group">
<label for="form-urgency">Priority</label>
<input type="number" class="form-control" id="form-urgency"
name="Urgency" placeholder="Urgency">
</div>
<div class="form-group">
<label for="form-circuitPortion">Circuit Portion</label>
<input type="text" class="form-control" id="form-circuitPortion"
name="Circuit_Portion" placeholder="Circuit Portion">
</div>
<div class="form-group">
<label for="form-quad">Quad</label>
<input type="text" class="form-control" id="form-quad"
name="Quad" placeholder="Quad">
</div>
<div class="form-group">
<label for="form-location">Location</label>
<input type="text" class="form-control" id="form-location"
name="Location" placeholder="location">
</div>
<div class="form-group">
<label for="form-poleSub">PolSub</label>
<input type="number" class="form-control" id="form-polSub"
name="PolSub" placeholder="PolSub">
</div>
<div class="form-group">
<label for="form-poleNumber">Pole Number</label>
<input type="number" class="form-control" id="form-poleNumber"
name="Pole_Number" placeholder="Pole Number">
</div>
<div class="form-group">
<label for="form-aerialName">Aerial Name</label>
<input type="text" class="form-control" id="form-aerialName"
name="Aerial_Name" placeholder="Aerial Name">
</div>
<div class="form-group">
<label for="form-workRequired">Work Required?</label>
<input type="text" class="form-control" id="form-workRequired"
name="Work_Required" placeholder="Work Required">
</div>
<div class="form-group">
<label for="form-long">GPS Longitude</label>
<input type="text" class="form-control" id="form-long"
name="long" placeholder="long">
</div>
<div class="form-group">
<label for="form-lat">GPS Latitude</label>
<input type="text" class="form-control" id="form-lat" name="lat"
placeholder="lat">
</div>
<div class="form-group">
<label for="form-notes">Comments</label>
<textarea class="form-control" id="form-comments"
name="Comments" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-
dismiss="modal">Close</button>
<button type="sumbit" class="btn btn-primary"
id="saveEventDataModal">Save</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
Here is the code for that should call the second modal called evenDataModal2
L.MarkerControl2 = L.Control.extend({
options: {
position: 'topleft',
url: 'http://echostorm.mynetgear.com:8080/geoserver/usa/ows',
userName: 'wfspost',
password: 'createfeature'
},
map: null,
marker: null,
binded: false,
onAdd: function (map) {
this.map = map;
var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
// link = L.DomUtil.create('a', 'glyphicon glyphicon-map-marker', container);
link = L.DomUtil.create('a', 'glyphicon glyphicon-fire', container);
link.href = '#';
link.title = 'Create a new thermal report';
link.innerHTML = '';
L.DomEvent.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', L.bind(this.startCreating, this));
map.on("editable:drawing:commit", L.bind(this.onMarkerAdd, this));
return container;
},
startCreating: function() {
this.marker = this.map.editTools.startMarker();
},
onMarkerAdd: function(e) {
this.nearestFeature = null;
this.findNearestPoints(e.layer.getLatLng());
},
onFormClosed: function() {
if (this.marker!=null) {
this.map.editTools.featuresLayer.removeLayer(this.marker);
this.marker = null;
}
},
findNearestPoints: function(latlng) {
var defaultParameters = {
service: 'WFS',
version: '1.0.0',
request: 'GetFeature',
typeName: 'usa:within5mi',
maxFeatures: 5,
outputFormat: 'text/javascript',
format_options: 'callback: nearestPoints',
srsName: 'EPSG:4326',
viewparams: 'radius:802;lon:'+latlng.lng+';lat:'+latlng.lat,
};
var parameters = L.Util.extend(defaultParameters);
$.ajax({
jsonp: false,
url: this.options.url + L.Util.getParamString(parameters),
dataType: 'jsonp',
jsonpCallback: 'nearestPoints',
success: L.bind(this.handleNearestPoints, this)
});
},
handleNearestPoints: function(data) {
this.clearModal();
this.setModalDate();
if (data && data.type=="FeatureCollection"
&& data.features && data.features.length
&& data.features.length > 0) {
this.fillModal(data.features[0]);
}
this.openPopup();
},
formatDate: function(date) {
var day = date.getDate();
return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+(day < 10 ? "0"+day : day);
},
clearModal: function() {
$('#eventDataModal2').find('input').each(
function() {
$(this).val("");
}
);
$('#eventDataModal2').find('textarea').each(
function() {
$(this).val("");
}
);
},
setModalDate: function() {
$("#form-patrolDate").val(this.formatDate(new Date()));
},
fillModal: function(feature) {
var props = feature.properties;
$("#form-region").val(props["Region"]);
$("#form-circuitID").val(props["Circuit_ID"]);
$("#form-circuitName").val(props["Circuit_Name"]);
$("#form-vendor").val(props["Vendor"]);
$("#form-quad").val(props["Quad"]);
},
openPopup: function() {
this.bindEvents();
$('#eventDataModal2').modal('show');
},
bindEvents: function() {
if (!this.binded) {
$('#eventDataModal2').on('hidden.bs.modal', L.bind(this.onFormClosed, this));
$("#saveEventDataModal2").on('click', L.bind(this.onSave, this))
this.binded = true;
}
},
onSave: function() {
var properties = this.getFormData(),
request = this.wfsBody("usa", "usa:pecotest", "geom", properties);
console.log(request);
this.makeRequest(request);
},
makeRequest: function(body) {
$.ajax({
method: "POST",
crossDomain: true,
url: this.options.url,
contentType: "text/xml",
dataType: "text",
data: body,
headers: {
"Authorization": "Basic " + btoa(this.options.userName + ":" + this.options.password)
},
jsonpCallback: 'datasave',
success: L.bind(this.onDataSave, this),
failure: function(r){console.log("AJAX Failure!");console.log(r);}
});
},
onDataSave: function(data) {
console.log(data);
},
getFormData: function() {
var result = {};
$('#eventDataModal2').find('input').each(
function() {
if (this.type=="checkbox") {
result[this.name] = this.checked ? "Yes" : "No";
} else {
result[this.name]=$(this).val();
}
}
);
$('#eventDataModal2').find('textarea').each(
function() {
result[this.name]=$(this).val();
}
);
return result;
},
wfsBody: function(namesapce, typeName, geometryField, properties) {
var xml;
xml ='<wfs:Transaction service="WFS" version="1.0.0"';
xml += ' xmlns:wfs="http://www.opengis.net/wfs"';
xml += ' xmlns:usa="http://census.gov"';
xml += ' xmlns:gml="http://www.opengis.net/gml">\n';
xml += ' <wfs:Insert>\n';
xml += ' <'+typeName+'>\n';
xml += ' <usa:'+geometryField+'>\n';
xml += this.marker.toGML()+"\n";
xml += ' </usa:'+geometryField+'>\n';
for (var k in properties) {
if (properties.hasOwnProperty(k)) {
xml += "<"+namesapce+":"+k+">";
xml += properties[k];
xml += "</"+namesapce+":"+k+">\n";
}
}
xml += ' </'+typeName+'>\n';
xml += ' </wfs:Insert>\n';
xml += '</wfs:Transaction>\n';
return xml;
}
});
The corresponding HTML for eventDataModal is exactly the same as the above html code except the id has been changed to eventDataModal2