How to drop empty elements and their keys in a JavaScript object? - javascript
I get objects of the type of:
{
personalData: {
name: "Diego",
last: "Aguilar",
mail: "diego#domain.com"
},
professionalData: {
almaMater: "BUAP",
courses: [
{},
{
name: "JavaScript Newbies",
tags: ["","",""]
}
]
}
}
So in that example, empty objects at professionalData.courses should be dropped and so the tags key at second object as their array elements are whole empty ones.
In general words, any time I find values being an empty object or array element, drop them. Also, if a key would get empty arrays or objects, drop them too.
Maybe jQuery or lodash/underscore would give a direct solution to this?
This is an example of an object stored at MongoDB:
{
"_id" : ObjectId("537e09c9896e05225cf50cb8"),
"datosPersonales" : {
"name" : "Maricela",
"lastname" : "Aguilar Flores",
"age" : "22",
"phone" : "2878710097",
"mobile" : "2878812505",
"email" : "af05_#hotmail.com",
"address" : "Carranza 168 Int 2"
},
"datosProfesionales" : {
"postgraduates" : [
{
"degree" : "Especialidad",
"title" : "Amor",
"cedula" : "ASFAS5"
},
{
"degree" : "Maestría",
"title" : "Romance",
"cedula" : "v"
}
],
"works" : [
"Universidad Hispano"
],
"freelances" : [ ],
"noPsychoWorks" : [ ],
"almaMater" : "BUAP",
"course" : "1987",
"cedula" : "SAFS555FSA",
"workAreas" : [
"Clínica",
"Laboral"
],
"freelance" : "true",
"noPsychoWork" : "false"
},
"interesesProfesionales" : {
"groups" : [
"Asociación de Psicólogos de Tuxtepec",
"Club de Toby"
],
"trainingTopics" : [
"Real Madrid",
"Cocina"
],
"belongsToSomewhere" : "true",
"activities" : [
"Conferencias y encuentros",
"Talleres"
],
"trainingAreas" : [
"Educativa"
],
"hasParticipated" : "true",
"wantsToBelong" : "true",
"whyToBelong" : "Futuro"
}
}
EDIT
This ugly objects are result of a bad handling in my Angular module.
That object came as a result of this code at Angular controller:
(function() {
var app = angular.module('PsicologosRegister', ['checklist-model'])
app.controller('PsicologoController', function($scope) {
this.psycho = psicologo
this.print = function() {
console.log(this.psycho)
}
this.toMongo = function() {
$.ajax({
type:"POST",
url:"/psychos",
data:this.psycho
})
}
})
app.controller('PersonalDataController', function() {
this.data = datos_Personales
})
app.controller('ProfessionalDataController', function() {
this.data = datos_Profesionales
})
app.controller('ProfessionalInterestsController', function() {
this.data = intereses_Profesionales
this.print = function() {
console.log(this.psycho)
}
})
app.controller('PosgraduateController', function() {
this.degrees = [
'Especialidad',
'Maestría',
'Doctorado'
]
this.postgraduates = _postgraduates
this.addPostgraduate = function() {
this.postgraduates.push({})
}
})
app.controller('WorkController', function() {
this.works = _works
this.addWork = function() {
this.works.push("")
}
})
app.controller('FreelanceController', function() {
this.freelances = _freelances
this.addFreelance = function() {
this.freelances.push("")
}
this.noFreelance = function() {
this.freelances = [""]
}
})
app.controller('NoPsychoWorkController', function() {
this.noPsychoWorks = _noPsychoWorks
this.addNoPsychoWork = function() {
this.noPsychoWorks.push("")
}
this.notNoPsychoWorks = function() {
this.noPsychoWorks = [""]
}
})
app.controller('TrainingTopicsController', function() {
this.trainingTopics = _trainingTopics
this.add = function() {
this.trainingTopics.push("")
}
})
app.controller('GroupsController', function() {
this.groups = _groups
this.add = function() {
this.groups.push("")
}
this.doesntBelongToAnywhere = function() {
this.groups = [""]
}
})
var _noPsychoWorks = [""]
var _freelances = [""]
var _works = [""]
var _postgraduates = [{}]
var _trainingTopics = [""]
var _groups = [""]
var _events = [{}]
var datos_Personales = {}
var datos_Profesionales = {postgraduates:_postgraduates, works: _works, freelances:_freelances, noPsychoWorks:_noPsychoWorks}
var intereses_Profesionales = {events:_events,groups:_groups,trainingTopics:_trainingTopics}
var psicologo = {
datosPersonales: datos_Personales,
datosProfesionales: datos_Profesionales,
interesesProfesionales: intereses_Profesionales
}
})()
This data is generated with the inputs from a web form, rendered with Angular. For elements at arrays I use ng-repeat. The problem is that as it's unknown whether there will be any freelances, postgraduates, etc. I start their belonging keys with Strings, for example.
This is my whole long markup:
<div id="formulario">
<div class="container" id="seccionRegistro1" ng-controller="PersonalDataController as personal">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="inputNombre" class="col-xs-2 control-label">Nombre(s)</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Nombre(s)" ng-model="personal.data.name" >
</div>
</div>
<div class="form-group">
<label for="inputApellidos" class="col-xs-2 control-label">Apellidos</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Apellidos" ng-model="personal.data.lastname">
</div>
</div>
<div class="form-group">
<label for="inputEdad" class="col-xs-2 control-label">Edad</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Edad" ng-model="personal.data.age">
</div>
</div>
<div class="form-group">
<label for="inputTel" class="col-xs-2 control-label">Teléfono</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Teléfono" ng-model="personal.data.phone">
</div>
</div>
<div class="form-group">
<label for="inputCel" class="col-xs-2 control-label">Celular</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Celular" ng-model="personal.data.mobile">
</div>
</div>
<div class="form-group">
<label for="inputMail" class="col-xs-2 control-label">e-mail</label>
<div class="col-xs-10">
<input type="email" class="form-control" placeholder="e-mail" ng-model="personal.data.email">
</div>
</div>
<div class="form-group">
<label for="inputFB" class="col-xs-2 control-label">Facebook</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Facebook" ng-model="personal.data.fb">
</div>
</div>
<div class="form-group">
<label for="inputDireccion" class="col-xs-2 control-label">Dirección</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Dirección" ng-model="personal.data.address">
</div>
</div>
<div class="col-xs-offset-2 col-xs-10">
<input type="button" class="btn btn-primary btnSeccion" id="btnSeccion1" value="Continuar"/>
</div>
</form>
</div>
<div class="container" id="seccionRegistro2" ng-controller="ProfessionalDataController as professional">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="inputAlmaMater" class="col-xs-2 control-label">Egresado de</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Egresado de" ng-model="professional.data.almaMater">
</div>
</div>
<div class="form-group">
<label for="inputAñoEgreso" class="col-xs-2 control-label">Año de egreso</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Año de egreso" ng-model="professional.data.course">
</div>
</div>
<div class="form-group">
<label for="inputCedula" class="col-xs-2 control-label">Cédula Profesional</label>
<div class="col-xs-10">
<input type="text" class="form-control" placeholder="Cédula Profesional" ng-model="professional.data.cedula">
</div>
</div>
<div class="form-group" ng-controller="PosgraduateController as postgraduate">
<label for="checkPosgrado" class="col-xs-2 control-label">Estudios de Posgrado</label>
<div ng-repeat="p in postgraduate.postgraduates track by $index">
<div class="padding-between-lines">
<label for="checkPosgrado" class="col-xs-2 control-label" ng-show="$index!=0"></label>
<div class="col-xs-2">
<select ng-options="t for t in postgraduate.degrees" ng-model="p.degree" class="form-control"><select>
</div>
<div class="col-xs-4">
<input type="text" ng-model="p.title" class="form-control inputPosgradoTitulo" placeholder="Título">
</div>
<div class="col-xs-3">
<input type="text" ng-model="p.cedula" class="form-control inputPosgradoCedula" placeholder="Cédula">
</div>
<div class="col-xs-1">
<input type="button" class="form-control" value="Añadir" ng-click="postgraduate.addPostgraduate()" ng-show="$index==0">
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="areaTrabajo" class="col-xs-2 control-label">Areas de la psicología en las que se desempeña</label>
<div class="col-xs-10" >
<label class="checkbox-inline" ng-repeat="area in ['Clínica', 'Social', 'Laboral', 'Educativa']">
<input type="checkbox" checklist-model="professional.data.workAreas" checklist-value="area"> {{area}}
</label>
</div>
</div>
<div class="form-group" ng-controller="WorkController as work">
<label for="inputTrabajo" class="col-xs-2 control-label">Institución de trabajo</label>
<div ng-repeat="w in work.works track by $index">
<div class="padding-between-lines">
<label for="inputTrabajo" class="col-xs-2 control-label" ng-show="$index!=0"></label>
<div class="col-xs-9">
<input type="text" class="form-control" placeholder="Institución de trabajo" ng-model="work.works[$index]">
</div>
<div class="col-xs-1">
<input type="button" class="form-control" value="Añadir" ng-click="work.addWork()" ng-show="$index==0">
</div>
</div>
</div>
</div>
<div class="form-group" ng-controller="FreelanceController as freelance">
<label for="trabajoIndependiente" class="col-xs-2 control-label">Desarrollo Profesional Independiente</label>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" ng-model="professional.data.freelance" name="optionsTrabajoIndependiente" value="true">
Sí
</label>
</div>
</div>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" ng-model="professional.data.freelance" ng-change="freelance.noFreelance()" name="optionsTrabajoIndependiente" value="false">
No
</label>
</div>
</div>
<div ng-repeat="f in freelance.freelances track by $index">
<div class="padding-between-lines">
<label class="col-xs-4" ng-hide="$index==0"></label>
<div class="col-xs-7">
<input type="text" class="form-control" placeholder="Desarrollo profesional independiente" ng-model="freelance.freelances[$index]" ng-disabled="professional.data.freelance=='false'">
</div>
<div class="col-xs-1">
<input type="button" class="form-control añadirTrabajoIndependiente" value="Añadir" ng-show="$index==0" ng-click="freelance.addFreelance()" ng-disabled="professional.data.freelance=='false'">
</div>
</div>
</div>
</div>
<div class="form-group" ng-controller="NoPsychoWorkController as noPsycho">
<label class="col-xs-2 control-label">Actividades de trabajo no relacionadas con la psicología</label>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" ng-model="professional.data.noPsychoWork" name="optionsTrabajoNoPsicologia" value="true">
Sí
</label>
</div>
</div>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" ng-model="professional.data.noPsychoWork" name="optionsTrabajoNoPsicologia" value="false" ng-change="noPsycho.notNoPsychoWorks()">
No
</label>
</div>
</div>
<div ng-repeat="n in noPsycho.noPsychoWorks track by $index">
<div class="padding-between-lines">
<label class="col-xs-4" ng-hide="$index==0"></label>
<div class="col-xs-7">
<input type="text" class="form-control" placeholder="Actividad" ng-model="noPsycho.noPsychoWorks[$index]" ng-disabled="professional.data.noPsychoWork=='false'">
</div>
<div class="col-xs-1">
<input type="button" class="añadirTrabajoNoPsicologia form-control" value="Añadir" ng-show="$index==0" ng-click="noPsycho.addNoPsychoWork()" ng-disabled="professional.data.noPsychoWork=='false'">
</div>
</div>
</div>
</div>
<div class="col-xs-offset-2 col-xs-10" ng-controller="PsicologoController as psi">
<input type="button" class="btn btn-primary btnSeccion" id="btnSeccion2" value="Continuar" ng-click="psi.print()"/>
</div>
</form>
</div>
<div class="container" id="seccionRegistro3" ng-controller="ProfessionalInterestsController as interests">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="actividadesInteres" class="col-xs-2 control-label">Actvidades profesionales en las que le gustaría participar</label>
<div class="col-xs-10" >
<label class="checkbox-inline" ng-repeat="area in ['Conferencias y encuentros', 'Cursos', 'Talleres', 'Diplomados', 'Maestría', 'Doctorado']">
<input type="checkbox" class="areaTrabajo" checklist-model="interests.data.activities" checklist-value="area"> {{area}}
</label>
</div>
</div>
<div class="form-group">
<label for="capacitacionInteres" class="col-xs-2 control-label">Areas de la psicología en las que le gustaría capacitarse</label>
<div class="col-xs-10">
<label class="checkbox-inline" ng-repeat="area in ['Clínica', 'Social', 'Laboral', 'Educativa']">
<input type="checkbox" class="areaTrabajo" checklist-model="interests.data.trainingAreas" checklist-value="area"> {{area}}
</label>
</div>
</div>
<div class="form-group" ng-controller="TrainingTopicsController as trainingTopic">
<label for="inputNombre" class="col-xs-2 control-label">¿Alguna temática en particular que le gustaría conocer o capacitarse?</label>
<div ng-repeat="tp in trainingTopic.trainingTopics track by $index">
<div class="padding-between-lines">
<label class="col-xs-2 control-label" ng-hide="$index==0"></label>
<div class="col-xs-9">
<input type="text" class="form-control" placeholder="Temática de interés" ng-model="trainingTopic.trainingTopics[$index]">
</div>
<div class="col-xs-1">
<input type="button" class="añadirTemaInteres form-control" value="Añadir" ng-show="$index==0" ng-click="trainingTopic.add()">
</div>
</div>
</div>
</div>
<div class="form-group" ng-controller="GroupsController as group">
<label for="checkPosgrado" class="col-xs-2 control-label">¿Pertenece a alguna agrupación relacionada con el campo de la psicología?</label>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" name="optionsPertenenciaAgrupacion" value="true" ng-model="interests.data.belongsToSomewhere">
Sí
</label>
</div>
</div>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" name="optionsPertenenciaAgrupacion" value="false" ng-model="interests.data.belongsToSomewhere" ng-change="group.doesntBelongToAnywhere()">
No
</label>
</div>
</div>
<div ng-repeat="g in group.groups track by $index">
<div class="padding-between-lines">
<label class="col-xs-2 control-label" ng-hide="$index==0"></label>
<div class="col-xs-7">
<input type="text" class="inputAgrupacion form-control" placeholder="Agrupación" ng-model="group.groups[$index]" ng-disabled="interests.data.belongsToSomewhere=='false'">
</div>
<div class="col-xs-1">
<input type="button" class="form-control" value="Añadir" ng-show="$index==0" ng-click="group.add()" ng-disabled="interests.data.belongsToSomewhere=='false'">
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="participacionEventos" class="col-xs-2 control-label">¿Ha participado con anterioridad en algún evento de la Asociación de Psicólogos de Tuxtepec?</label>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" name="optionsParticipacionEventos" value="true" ng-model="interests.data.hasParticipated">
Sí
</label>
</div>
</div>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" name="optionsParticipacionEventos" value="false" ng-model="interests.data.hasParticipated">
No
</label>
</div>
</div>
<div class="col-xs-8">
<select multiple class="form-control">
<option value="abrazoterapia">Abrazoterapia</option>
<option value="tallerMujeres">Taller autoestima mujeres</option>
</select>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<h4>Le gustaría participar como miembro activo de la Asociación de Psicólogos de Tuxtepec A.C</h4>
</div>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" name="optionsMiembro" value="true" ng-model="interests.data.wantsToBelong">
Sí
</label>
</div>
</div>
<div class="col-xs-1">
<div class="radio">
<label>
<input type="radio" name="optionsMiembro" value="false" ng-model="interests.data.wantsToBelong">
No
</label>
</div>
</div>
<div class="col-xs-4">
<textarea class="form-control" rows="3" placeholder="¿Por qué?" ng-model="interests.data.whyToBelong"></textarea>
</div>
</div>
<div class="col-xs-offset-2 col-xs-10" ng-controller="PsicologoController as psi">
<input type="button" class="btn btn-primary btnSeccion" id="btnSeccion3" value="Finalizar" ng-click="psi.toMongo()"/>
</div>
</form>
</div>
</div>
Why not just keep it simple and create a solution that works for the given object. You can always refactor it and then come up with a more elegant solution after that. But you'll need to establish a working point just to get you started. I'd also suggestion caution to creating a complex solution too - because after all, schemas can change ( no matter how many times you may be told they won't ).
I'd start out by just creating separate methods to evaluate each piece individually. For instance, create a solution to work with each of your parent keys ( datosPersonales, datosProfesionales, interesesProfesionales ) that will just determine if they are empty first.
Next, create a solution to work with each sibling of those parents ( postgraduates would have its own routine to check for empty values, works would have its own, etc. ).
Follow this for each branch in the object.
Once you get something that can evaluate each one of them, you'll then be able to start refactoring by working your way up from the bottom-most level ( for instance, tags would be the bottom most level in your first object example ).
Start combining like methods that seem to do the same job and create a universal method that works for each like structure.
And so on..
Once you get a solution close to what you want, I think that's when you'll either be ready to say "hey, can someone help me refactor this even more?".
A good utility kit to help you on your way is underscore: http://underscorejs.org/#map
hope that helps.
Related
A form isn't working when showing mobile view
I'm trying to set a mobile view for my site. In this particular case i have to show two different forms according to the width of the page (under 400px it shows the "login-form-mobile"). The form submit is handled by a js function, the problem is that the function works only on the first form (over 400px), the second one submit without checking if inputs are empty etc... Does someone knows why? function validaReg() { if (document.formregistrazione.nome.value === "") { togglediv("invalidname"); invalidForm("nome"); return false; } if (document.formregistrazione.email.value === "") { togglediv("invalidemail"); invalidForm("email"); return false; } if (document.formregistrazione.username.value === "") { togglediv("invalidusername"); invalidForm("username"); return false; } if (document.formregistrazione.password.value === "") { togglediv("invalidpassword"); invalidForm("password"); return false; } if (document.formregistrazione.ripeti_password.value === "") { togglediv("invalidrippassword"); invalidForm("ripeti_password"); return false; } var pw1 = document.getElementById("password"); var pw2 = document.getElementById("ripeti_password"); var id = document.getElementById("invalidrippassword"); if (pw2.value != pw1.value) { pw2.classList.add("is-invalid"); id.style.display = 'block'; return false; } return true; } <div id="login-form" class="container-form fade-in-image"> <div class="fade-in-image col-md-12 mb-3"> <img id="logo" class="img-fluid" src="Fubles.png"> <img id="logo-mobile" class="img-fluid" src="Fubles-mobile.png"> </div> <form class="ctr-form" style="width:50%;" method="post" name="formregistrazione" onSubmit="return validaReg();" action="checkReg.php"> <div> <div class="row justify-content-md-center"> <div class="col-md-3 mb-3"> <label for="nome">Nome</label> <input type="text" class="form-control" id="nome" name="inputname" placeholder="Name" onChange="retogglediv('invalidname'); retogglediv2('nome');"> <div id="invalidname" class="invalid-feedback" style="display: none;"> Inserire un nome </div> </div> <div class="col-md-3 mb-3"> <label for="cognome">Email</label> <input type="email" class="form-control" id="email" name="inputemail" placeholder="Email" onChange="retogglediv('invalidemail'); retogglediv2('email');"> <div id="invalidemail" class="invalid-feedback" style="display: none;"> Inserire una email </div> </div> <div class="col-md-3 mb-3"> <label for="username">Username</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text" id="inputGroupPrepend3">#</span> </div> <input type="text" class="form-control" id="username" name="inputusername" placeholder="Username" aria-describedby="inputGroupPrepend3" onChange="retogglediv('invalidusername'); retogglediv2('username');"> <div id="invalidusername" class="invalid-feedback" style="display: none;"> Scegli un username </div> </div> </div> </div> <div class="row justify-content-md-center"> <div class="col-md-3 mb-3"> <label for="stato">Password</label> <input type="password" class="form-control" id="password" name="inputpassword" placeholder="Password" onChange="retogglediv('invalidpassword'); retogglediv2('password');"> <div id="invalidpassword" class="invalid-feedback" style="display: none;"> Scegli una password </div> </div> <div class="col-md-3 mb-3"> <label for="cap">Ripeti password</label> <input type="password" class="form-control" id="ripeti_password" placeholder="Password" onChange="retogglediv('invalidrippassword'); retogglediv2('ripeti_password');"> <div id="invalidrippassword" class="invalid-feedback" style="display: none;"> La password deve corrispondere! </div> </div> <div class="col-md-2 mb-3"> <div class="custom-control custom-radio"> <input type="radio" id="male" name="sex" value="M" class="custom-control-input" checked> <label class="custom-control-label" for="male">Uomo</label> </div> <div class="custom-control custom-radio"> <input type="radio" id="female" name="sex" value="F" class="custom-control-input"> <label class="custom-control-label" for="female">Donna</label> </div> </div> </div> <div class="row justify-content-md-center"> <div class="col-md-3 mb-3"> <button class="btn btn-signup justify-content-md-center" name="submit" type="submit">Registrati</button> </div> </div> </div> </form> </div> <div style="overflow-y: scroll; margin-top: 5%;" id="login-form-mobile" class="container-form fade-in-image"> <div class="fade-in-image col-md-12 mb-3"> <img id="logo" class="img-fluid" src="Fubles.png"> <img id="logo-mobile" class="img-fluid" src="Fubles-mobile.png"> </div> <form method="post" name="formregistrazione" onSubmit="return validaReg();" action="checkReg.php"> <div> <div class="row justify-content-md-center"> <div class="col-md-3 mb-3"> <label for="nome">Nome</label> <input type="text" class="form-control" id="nome" name="inputname" placeholder="Name" onChange="retogglediv('invalidname'); retogglediv2('nome');"> <div id="invalidname" class="invalid-feedback" style="display: none;"> Inserire un nome </div> </div> <div class="col-md-3 mb-3"> <label for="cognome">Email</label> <input type="email" class="form-control" id="email" name="inputemail" placeholder="Email" onChange="retogglediv('invalidemail'); retogglediv2('email');"> <div id="invalidemail" class="invalid-feedback" style="display: none;"> Inserire una email </div> </div> <div class="col-md-3 mb-3"> <label for="username">Username</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text" id="inputGroupPrepend3">#</span> </div> <input type="text" class="form-control" id="username" name="inputusername" placeholder="Username" aria-describedby="inputGroupPrepend3" onChange="retogglediv('invalidusername'); retogglediv2('username');"> <div id="invalidusername" class="invalid-feedback" style="display: none;"> Scegli un username </div> </div> </div> </div> <div class="row justify-content-md-center"> <div class="col-md-3 mb-3"> <label for="stato">Password</label> <input type="password" class="form-control" id="password" name="inputpassword" placeholder="Password" onChange="retogglediv('invalidpassword'); retogglediv2('password');"> <div id="invalidpassword" class="invalid-feedback" style="display: none;"> Scegli una password </div> </div> <div class="col-md-3 mb-3"> <label for="cap">Ripeti password</label> <input type="password" class="form-control" id="ripeti_password" placeholder="Password" onChange="retogglediv('invalidrippassword'); retogglediv2('ripeti_password');"> <div id="invalidrippassword" class="invalid-feedback" style="display: none;"> La password deve corrispondere! </div> </div> <div class="col-md-2 mb-3"> <div class="custom-control custom-radio"> <input type="radio" id="male" name="sex" value="M" class="custom-control-input" checked> <label class="custom-control-label" for="male">Uomo</label> </div> <div class="custom-control custom-radio"> <input type="radio" id="female" name="sex" value="F" class="custom-control-input"> <label class="custom-control-label" for="female">Donna</label> </div> </div> </div> <div class="row justify-content-md-center"> <div class="col-md-3 mb-3"> <button class="btn btn-signup justify-content-md-center" name="submit" type="submit">Registrati</button> </div> </div> </div> </form> </div>
Your form is not working because you have a bug in the lines that start with document.formregistrazione. You are trying to read a value from undefined. Instead you can access your field value like this document.formregistrazione["0"]["0"].value. Note: if you are trying to test the second form replace document.formregistrazione["0"]["0"].value by document.formregistrazione["1"]["0"].value! (Replace the first "0" by "1") function validaReg() { console.log(document.formregistrazione); if (document.formregistrazione["0"]["0"].value === "") { togglediv("invalidname"); invalidForm("nome"); return false; } if (document.formregistrazione["0"]["1"].value === "") { togglediv("invalidemail"); invalidForm("email"); return false; } if (document.formregistrazione["0"]["2"].value === "") { togglediv("invalidusername"); invalidForm("username"); return false; } if (document.formregistrazione["0"]["3"].value === "") { togglediv("invalidpassword"); invalidForm("password"); return false; } if (document.formregistrazione["0"]["4"].value === "") { togglediv("invalidrippassword"); invalidForm("ripeti_password"); return false; } var pw1 = document.getElementById("password"); var pw2 = document.getElementById("ripeti_password"); var id = document.getElementById("invalidrippassword"); if (pw2.value != pw1.value) { pw2.classList.add("is-invalid"); id.style.display = 'block'; return false; } return true; }
How to customize key-value pairs when using .serializeArray() Javascript?
Code example: $('#simpan').click(function(){ var data = $('.serialize').serializeArray(); console.log(data) }) <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script> <div class="row"> <div class="col-lg-12"> <label><input type="radio" name="perkawinan" id="" class="form-control-sm serialize" value="belum kawin" data-title="Perkawinan"><b> Belum Kawin</b></label> <label><input type="radio" name="perkawinan" id="" class="form-control-sm serialize" value="kawin" data-title="Perkawinan"><b> Kawin</b></label> <label><input type="radio" name="perkawinan" id="" class="form-control-sm serialize" value="duda/janda" data-title="Perkawinan"><b> Duda/Janda</b></label> <label><input type="radio" name="perkawinan" id="" class="form-control-sm serialize" value="bawah umur" data-title="Perkawinan"><b> Bawah Umur</b></label> </div> </div> <div class="row"> <div class="col-lg-12"> <input type="text" name="pekerjaan" id="" class="form-control form-control-sm serialize" placeholder="Pekerjaan..." data-title="Pekerjaan"> </div> </div> <div class="row"> <button type="button" class="btn btn-sm btn-outline-success" id="simpan">SIMPAN</button> </div> The result will be an array of object with key->value pairs of name and value. How to add additional key when we execute .serializeArray()? The desired output is : [ { "name": "perkawinan", "value": "kawin", "title": "Status Perkawinan", "type": "radio" }, { "name": "pekerjaan", "value": "", "title": "Pekerjaan Pasien", "type": "text" } ]
Sorry for the late reply, was busy with sme works... You can do this in two way HTML <div class="container"> <div class="row"> <form action="" method="post" enctype="multipart/form-data" class="serialize"> <div clas="col-xs-12 col-sm-12 col-md-12 col-lg-12"> <div class="custom-control custom-radio custom-control-inline"> <input type="radio" name="perkawinan" class="custom-control-input" value="Belum Kawin" data-title="Title 1"> <label class="custom-control-label" for="customRadioInline1">Belum Kawin</label> <input type="radio" name="perkawinan" class="custom-control-input" value="Duda/Janda" data-title="Title 2"> <label class="custom-control-label" >Duda/Janda</label> </div> <div class="form-group" style="margin:15px 0"> <label>Pekerjaan</label> <input type="text" name="pekerjaan" class="form-control" placeholder="Pekerjaan" data-title="Title 3"> </div> </div> <div clas="col-xs-12 col-sm-12 col-md-12 col-lg-12"> <input name="submit" type="button" value="Submit" id="simpan" class="btn btn-success"> </div> </form> <div clas="col-xs-12 col-sm-12 col-md-12 col-lg-12" id="output" style="margin-top:20px"></div> </div> </div> Method 1 This will return the object even if the text box value is null <script type="text/javascript"> $(function() { $('#simpan').on('click',function() { var data = $('.serialize :input').serializeArray(); var data = $.each(data, function(i,obj){obj.title = $("input[name='"+obj['name']+"']").data('title');obj.type = $("input[name='"+obj['name']+"']").attr('type');}); $('#output').html(JSON.stringify(data)) }) }); </script> Method 2 This will return objects which have values <script type="text/javascript"> $(function() { $('#simpan').on('click',function() { var data = $( ".serialize :input").filter(function () {return !!this.value;}).serializeArray(); var data = $.each(data, function(i,obj){obj.title = $("input[name='"+obj.name+"']").data('title');obj.type = $("input[name='"+obj.name+"']").attr('type');}); $('#output').html(JSON.stringify(data)) }) }); </script> here is a working fiddle JSFiddle
Submit a form in the background with ajax
I have the following problem, I am using Prestashop and I need a form to make a submit in the background, I have investigated and I found a way to do it with ajax but I need the url and data parameter that I do not know how to get them since the form is this. As you can see, the form has no action and the data is not clearly visible, this would be the way I have in mind to do it with ajax: $(document).ready(function() { $("#makePdfCatalogue").submit(function(e) { e.preventDefault(); var dataString = $("#makePdfCatalogue").serialize(); //this way i cant get the data console.log(dataString); $.ajax({ type: "POST", url: "", //action doenst appear data: dataString, success: function(msg) { console.log('working: ' + msg); }, error: function(msg) { //console.log('not working ' + msg); } }); }) }) <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <form id="makePdfCatalogue" name="makePdfCatalogue" method="POST" enctype="multipart/form-data"> <div class="row"> <div class="col-md-6"> <fieldset> <legend>Categorías</legend> <div class="form-group"> <label class="" for="name">{l s="Selecciona la categoría/s que deseas exportar" mod="custompdfexport"}</label> {$categories_tree} </div> </fieldset> </div> <div class="col-md-6"> <fieldset> <legend>Datos empresa</legend> <div class="row"> <div class="col-md-12"> <div class="form-group"> <label class="" for="name">Nombre Empresa</label> <input type="text" name="name" placeholder={l s="Nombre Empresa..." mod="custompdfexport" } class="form-control" id="name"> </div> </div> </div> <div class="row"> <div class="col-md-12"> <div class="form-group"> <label class="" for="contact">Datos contacto</label> <input type="text" name="contact" placeholder={l s="Datos Contacto..." mod="custompdfexport" } class="form-control" id="contact"> </div> </div> </div> <div class="row"> <div class="col-md-12"> <div class="form-group"> <label class="" for="logo">Logo empresa</label> <input type="file" name="logo" placeholder={l s="logo Empresa..." mod="custompdfexport" } class="form-control" id="logo"> </div> </div> </div> </fieldset> <fieldset> <legend>Opciones</legend> <div class="row"> <div class="col-md-3"> <div class="form-group"> <label class="" for="form-password">{l s="Diseño" mod="custompdfexport"}</label> <ul> <li> <input type="radio" name="format" class="form-control" value="2" id="format-2"><label for="format-2">{l s="2 columnas" mod="custompdfexport"}</label> </li> <li> <input type="radio" name="format" class="form-control" value="3" id="format-3"><label for="format-3">{l s="3 columnas" mod="custompdfexport"}</label> </li> <li> <input type="radio" name="format" class="form-control" value="4" id="format-4"><label for="format-4">{l s="4 columnas" mod="custompdfexport"}</label> </li> </ul> </div> </div> <div class="col-md-5"> <div class="form-group"> <label class="" for="form-password">Opciones</label> <div class="form-group"><input type="checkbox" name="options[]" class="form-control" id="opt-wt" value="wt"><label for="opt-wt">{l s="Mostrar Precios con Iva" mod="custompdfexport"}</label></div> <div class="form-group"><input type="checkbox" name="options[]" class="form-control" id="opt-wot" value="wot"><label for="opt-wot"> {l s="Mostrar Precios sin Iva" mod="custompdfexport"}</label></div> <div class="form-group"><input type="checkbox" name="options[]" class="form-control" id="opt-ref" value="reference"><label for="opt-ref">{l s="Mostrar referencia" mod="custompdfexport"}</label></div> <div class="form-group"><input type="checkbox" name="options[]" class="form-control" id="opt-link" value="link"><label for="opt-link">{l s="Enlazar productos con web" mod="custompdfexport"}</label></div> </div> </div> <div class="col-md-4"> <div class="form-group"> <label class="" for="revenue">Margen comercial (%)</label> <input type="text" name="revenue" placeholder={l s="Margen comercial..." mod="custompdfexport" } class="form-control" id="revenue" style="width: 100px;"> </div> <div class="form-group"> <label class="" for="revenue">Descuento (%)</label> <input type="text" name="reduction" placeholder={l s="Descuento..." mod="custompdfexport" } class="form-control" id="reduction" style="width: 100px;"> </div> </div> </div> <div class="row"> <div class="col-md-6"> <label class="" for="form-password">Ordenar</label> <div class="form-group"><input type="radio" name="order" class="form-control" id="order-asc" value="price_asc"><label for="order-asc">{l s="Por precio de Menor a Mayor" mod="custompdfexport"}</label></div> <div class="form-group"><input type="radio" name="order" class="form-control" id="order-desc" value="price_desc"><label for="order-desc">{l s="Por precio de Mayor a Menor" mod="custompdfexport"}</label></div> </div> <div class="col-md-6"> <label class="" for="form-password">Stock</label> <div class="form-group"><input type="checkbox" name="stock" class="form-control" id="stock" value="stock"><label for="stock">{l s="Seleccionar sólo artículos con stock"}</label></div> </div> </div> </fieldset> <br> <input type="hidden" name="token" value="{$token|escape:'html':'UTF-8'}" /> <input type="submit" name="submitMakePdfCatalogue" id="submitMakePdfCatalogue" value="{l s='Generar' mod='custompdfexport'}" class="exclusive" /> </div> </div> </form> any suggestion of how to get those parameters...
I already solved the data problem and I also know that the action is catalogue.php but I don't know how to locate it with the url since it is inside a prestashop module. I tried something like that but it gave me an error 500 that is, it is not the correct path $(document).ready(function() { $("#makePdfCatalogue").submit(function(e) { e.preventDefault(); var dataString = $("#makePdfCatalogue").serialize(); //solved $.ajax({ type: "POST", headers: { "cache-control": "no-cache" }, url: baseDir + 'modules/custompdfexport/controllers/front/catalogue.php',//is not the correct url data: dataString, success: function(msg) { console.log('working: '+msg); }, error: function(msg) { console.log('not working '+msg); } }); }) })
This is how you can get a link to your controller: Context::getContext()->link->getModuleLink('custompdfexport', 'catalogue'); In your case you are calling controller via AJAX so you need pass the ajax parameter in url like this: Context::getContext()->link->getModuleLink('custompdfexport', 'catalogue', array('ajax' => true)); If you have URL rewriting enabled your URL will look something like: http://<shop_domain>/en/module/custompdfexport/catalogue?ajax=true Source
Dynamic multiselect feature
I am creating the fields dynamically in HTML using this JS, and in multiselect I'm using bootstrap multiselect here is the code https://bootsnipp.com/snippets/Ekd8P when I click on the add more button it creates the form dynamically. js code for creating a form dynamically : $(function() { // Remove button $(document).on( 'click', '[data-role="dynamic-fields"] > .form-horizontal [data-role="remove"]', function(e) { e.preventDefault(); $(this).closest('.form-horizontal').remove(); } ); // Add button var i = 1; $(document).on( 'click', '[data-role="dynamic-fields"] > .form-horizontal [data-role="add"]', function(e) { e.preventDefault(); var container = $(this).closest('[data-role="dynamic-fields"]'); new_field_group = container.children().filter('.form-horizontal:first-child').clone(); new_field_group.find('input').each(function() { if (this.name == 'tags[0]') { $(this).tagsinput('destroy'); $(this).tagsinput('removeAll'); this.name = this.name.replace('[0]', '[' + i + ']'); var new_container = $(this).closest('[class="form-group"]'); new_container.find(".bootstrap-tagsinput:first").remove(); } else { $(this).val(''); } }); new_field_group.find('select').each(function() { if (this.name == 'addons[0]') { $(this).multiselect('rebuild'); this.name = this.name.replace('[0]', '[' + i + ']'); var new_container = $(this).closest('[class="multiselect-native-select"]'); new_container.find(".multiselect-native-select > .multi").remove(); } else { $(this).val(''); } }); i += 1; container.append(new_field_group); } ); }); and html code for form elements: <form action="" method="post" novalidate="novalidate" enctype="multipart/form-data"> {{ csrf_field() }} <div data-role="dynamic-fields"> <div class="form-horizontal"> <div class="row"> <div class="col-sm-4"> <div class="form-group"> <label for="Firstname5" class="col-sm-3">Enter Dish Name</label> <div class="col-sm-8"> <input type="text" class="form-control" id="Name1" name="Name[]" required data-rule-minlength="2"> </div> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="Firstname5" class="col-sm-3">Enter Dish Price</label> <div class="col-sm-8"> <input type="text" class="form-control" id="Price" name="Price[]" required data-rule-minlength="2"> </div> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="Firstname5" class="col-sm-3">Select Food Type</label> <div class="col-sm-8"> <select id="select1" class="form-control" name="select[]" required> #foreach($types as $type) <option value="{{$loop->iteration}}">{{$type->food_type_name}}</option> #endforeach </select> <p class="help-block" data-toggle="tooltip" data-placement="bottom" title="xyz"><i class="md md-info"></i></p> </div> </div> </div> </div> <div class="row"> <div class="col-sm-4"> <div class="form-group"> <label for="Firstname5" class="col-sm-3">Dish Description</label> <div class="col-sm-8"> <textarea name="Description[]" id="field-value" class="form-control" rows="1"></textarea> </div> </div> </div> <div class="col-sm-4 contacts"> <div class="form-group"> <label class="col-sm-3" for="rolename">Add Addons</label> <div class="col-sm-8"> <select id="dates-field2" class="multiselect-ak form-control" name="addons[0]" id="trigger3" data-role="multiselect" multiple="multiple"> #foreach($addons as $addon) <option value="{{$addon->addonid}}">{{$addon->addon_name}}</option> #endforeach </select> </div> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="Firstname5" class="col-sm-3">Enter Tags</label> <div class="col-sm-8"> <input type="text" value="" name="tags[0]" class="form-control" data-role="tagsinput" placeholder="e.g. spicy, healthy" /> </div> </div> </div> </div> <div class="row"> <div class="col-sm-4"> <div class="col-sm-4"> <div class="checkbox checkbox-styled"> <label><em>Half Plate Price</em> <input type="checkbox" value="" class="trigger2" id="trigger2" name="question"> </label> </div> </div> <div class="col-sm-4"> <div id="hidden_fields2" class="hidden_fields2" style="display:none;"> <input type="text" id="hidden_field2" name="Price2[]" placeholder="Please Enter" class="form-control"> </div> </div> </div> <div class="col-sm-4"> <div class="col-sm-5"> <div class="checkbox checkbox-styled"> <label><em>Quarter Plate Price</em> <input type="checkbox" value="" class="trigger" id="trigger" name="question"> </label> </div> </div> <div class="col-sm-4"> <div id="hidden_fields" class="hidden_fields" style="display:none;"> <input type="text" id="hidden_field" name="Price3[]" placeholder="Please Enter" class="form-control"> </div> </div> </div> </div> <br> <button class="btn btn-delete" data-toggle="tooltip" data-placement="bottom" title="Delete Field" data-role="remove"> Delete Item </button> <button class="btn ink-reaction btn-raised btn-primary" data-toggle="tooltip" data-placement="bottom" title="Add More Field" data-role="add"> Add More Items </button> </div> <!-- /div.form-inline --> </div> <!-- /div[data-role="dynamic-fields"] --> <div class="form-group"> <button type="submit" name="submit" href="#" class="btn ink-reaction btn-raised btn-primary" style="margin-top: -62px;margin-left: 160px;">Submit Items</button> </div> <!--end .form-group --> </form> The issue is that when I click on the add more item it reflects the multiselect dropdown twice as you see in this image. I want that if I click on the add more item button it restates the multiselect dropdown as in the first state. see this jsfiddle.net/akshaycic/svv742r7/7 it will clear all your doubt. on click plus button it is not reflect to "none selected" state it will remain in its initial state. Any leads would be helpful. Thank you in advance.
Form.Serialize with checkbox array
I'm submitting a form through JQuery by using the form.serialize method. But that same form has an array of checkboxes, which is dynamically genetrated by a PHP function This is the form: <form class="form" id="formNewClient" role="form"> <ul class="nav nav-tabs"> <li class="active"><i class="fa fa-user"></i> Dados Cliente</li> <li><i class="fa fa-phone"></i> Dados Phonepark</li> </ul> <div class="tab-content"> <div class="tab-pane active" id="clientdata"> <div class="row"> <div class="col-md-12"> <div class="page-header"><h3>Dados Pessoais</h3></div> </div> </div> <div class="row"> <div class="form-group col-md-8"> <label for="name">Nome Completo:*</label> <input type="text" name="clientName" class="form-control" placeholder="Nome Completo do Utilizador"> </div> </div> <div class="row"> <div class="form-group col-md-8"> <label for="email">Email:</label> <input type="text" name="clientEmail" class="form-control" placeholder="Email Utilizador"> </div> </div> <div class="row"> <div class="form-group col-md-8"> <label for="addressone">Morada:</label> <input type="text" name="clientAddressone" class="form-control" placeholder="Morada do Utilizador"> </div> </div> <div class="row"> <div class="form-group col-md-6"> <label for="address2">Morada (cont.):</label> <input type="text" name="clientAddresstwo" class="form-control" placeholder="Morada do Utilizador (cont.)"> </div> <div class="form-group col-md-3"> <label for="postalcode">Código Postal:</label> <input type="text" name="clientCPostal" class="form-control" placeholder="Código Postal"> </div> <div class="form-group col-md-3"> <label for="city">Localidade:</label> <input type="text" name="clientCity" class="form-control" placeholder="Localidade"> </div> </div> <div class="row"> <div class="form-group col-md-4"> <label for="clientNif">NIF</label> <input type="text" name="clientNif" class="form-control " placeholder="NIF"> </div> <div class="form-group col-md-4"> <label for="clientBirthdate">Data de Nascimento</label> <div class="form-group"> <div class='input-group date' id='inputendDate' data-date-format="YYYY/MM/DD"> <input type='text' name="clientBirthdate" class="form-control" /> <span class="input-group-addon"><span class="glyphicon glyphicon-time"></span> </div> </div> </div> <div class="form-group col-md-4"> <label for="sex">Sexo:</label> <br> <label class="radio-inline"> <input type="radio" name="optionsRadioSex" value="M"> Masculino </label> <label class="radio-inline"> <input type="radio" name="optionsRadioSex" value="F"> Feminino </label> </div> </div> </div> <!--END CLIENTDATA--> <div class="tab-pane" id="phoneparkdata"> <div class="row"> <div class="col-md-12"> <div class="page-header"> <h3>Dados Phonepark</h3> </div> </div> </div> <div class="row"> <div class="col-md-12"><h4>Documentos:</h4></div> <div class="form-group col-md-4"> <label for="document">Tipo de Documento:</label> <select name="documenttype" class="form-control"> <?php selectListDocuments();?> </select> </div> <div class="form-group col-md-4"> <label for="documentNumber">Número do Documento:*</label> <input type="text" name="documentNumber" class="form-control"> </div> <div class="form-group col-md-4"> <label for="documentNumber">Número do Documento (Secundário):</label> <input type="text" name="documentNumberSec" class="form-control"> </div> </div> <div class="row"> <div class="col-md-12"><h4>Comunicações:</h4></div> <div class="form-group col-md-4"> <label for="phone1">Telemóvel:*</label> <input type="text" name="clientPhonePri" class="form-control"> </div> <div class="form-group col-md-4"> <label for="phone2">Telemóvel Secundário:</label> <input type="text" name="clientPhoneSec" class="form-control"> </div> </div> <div class="row"> <div class="form-group col-md-6"> <h4>Perfil:</h4> <label for="profile">Perfil(s) a utilizar:*</label> <?php profileCheckBoxes(); ?> </div> </div> <div class="row"> <div class="form-group col-md-6"> <label for="activationDate">Data de Activação:</label> <div class="form-group"> <div class='input-group date' id='inputactivationDate' data-date-format="YYYY/MM/DD hh:mm"> <input type='text' name="clientActivationTime" class="form-control" /> <span class="input-group-addon"><span class="glyphicon glyphicon-time"></span> </div> </div> </div> <div class="form-group col-md-6"> <label for="limitDate">Data de Limite:</label> <div class="form-group"> <div class='input-group date' id='inputendDate' data-date-format="YYYY/MM/DD hh:mm"> <input type='text' name="clientDeactivationTime" class="form-control" /> <span class="input-group-addon"><span class="glyphicon glyphicon-time"></span> </div> </div> </div> </div> </div> <!--END PHONEPARKDATA--> </div> <!--END TAB-CONTENT--> <div class="row"> <div class="col-md-4 col-lg-4 pull-right"> <button type="submit" class="btn btn-success" name="submitNewClient" id="submitNewClient"><i class="fa fa-plus"></i> Adicionar Cliente</button> <button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times"></i> Cancelar</button> </div> </div> </form> And this is the php function that generates the checkboxes: function profileCheckBoxes(){ $queryListProfiles = "SELECT * FROM perfil"; $listProfiles = mysqli_query($GLOBALS['dbc'],$queryListProfiles); $numProfiles = mysqli_num_rows($listProfiles); if($numProfiles !=""){ while($row = mysqli_fetch_array($listProfiles)){ ?> <label class="checkbox-inline"> <input type="checkbox" value="<?php echo $row['id']?>" name="profiles[]"> <?php echo $row['Nome']; ?> </label> <?php } } } How can I submit the form with form.serialize in Jquery and in the PHP side process the checkbox so I can extract the values from the checkbox array?
This jQuery documentation page explains how to use the serialize function: http://api.jquery.com/serialize/ If you then pass the output to your php page using POST, in the PHP script the checked values will be stored in $_POST['profiles'] as an array. So to loop through the values of the checked boxes you could use: foreach ($_POST['profiles'] as $profile) { //process code here }
jQuery's form.serialize only pass checksboxes that are checked. if you want all your checkboxes to get passed to your server consider to generate also hidden inputs to store those values. I would also change the checkboxes name to "profiles"