webForumDet fria alternativet

Funktion för formulärvalidering - hur snygga till?

JavaScript

20 svar · 1 162 visningar · startad av m_soderlund

Medlem sedan sep. 20026 425 inlägg
Frågan#1

Jag har skapat en funktion för att validera output från ett formulär. Om man lämnat ett obligatoriskt fält i formuläret så markeras fältet med röd tjock ram och en text skrivs ut i ett span-element intill formulärfältet.

Jag undrar hur jag skulle kunna göra denna funktion snyggare? Den fungerar jättebra men jag är nyfiken.

Så här ser javascriptfunktionen ut:

<!--
function vali(){

    var username,password1,password2,name,email
    
    username = document.getElementById("f_username").value;
    password1 = document.getElementById("f_password1").value;
    password2 = document.getElementById("f_password2").value;
    name = document.getElementById("f_name").value;
    email = document.getElementById("f_email").value;
    
    if (username=="") {
        document.getElementById('sf_username').innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn.';
        document.getElementById('f_username').style.border='solid 3px #c00';
        return false;
    }
    else if (password1=="") {
        document.getElementById('sf_password1').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord.';
        document.getElementById('f_password1').style.border='solid 3px #c00';
        return false;
    }
    else if (password2=="") {
        document.getElementById('sf_password2').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord.';
        document.getElementById('f_password2').style.border='solid 3px #c00';
        return false;
    }
    else if (name=="") {
        document.getElementById('sf_name').innerHTML = 'Du m&aring;ste ange ditt namn.';
        document.getElementById('f_name').style.border='solid 3px #c00';
        return false;
    }
    else if (email=="") {
        document.getElementById('sf_email').innerHTML = 'Du m&aring;ste ange en e-postadress.';
        document.getElementById('f_email').style.border='solid 3px #c00';
        return false;
    }
    else if (password1 != password2) {
        document.getElementById('sf_password2').innerHTML = '';
        document.getElementById('sf_password2').innerHTML = 'Du m&aring;ste ange samma l&ouml;senord tv&aring; g&aring;nger.';
        document.getElementById('f_password2').style.border='solid 3px #c00';
        return false;
    }
    else {
        return true;
        }
}

//-->

Kom med tips och tack på förhand!

Medlem sedan dec. 20025 483 inlägg
#2

Hej! :)

Spontant skulle jag göra följande ändringar:

function vali(){

    var username,password1,password2,name,email,sf_password2,border_style;
    
    username = document.getElementById("f_username");
    password1 = document.getElementById("f_password1");
    password2 = document.getElementById("f_password2");
    name = document.getElementById("f_name");
    email = document.getElementById("f_email");
    sf_password2 = document.getElementById("sf_password2");
    border_style = "solid 3px #c00";
    
    if (username.value=="") {
        document.getElementById('sf_username').innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn.';
        username.style.border=border_style;
        return false;
    }
    if (password1.value=="") {
        document.getElementById('sf_password1').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord.';
        password1.style.border=border_style;
        return false;
    }
    if (password2.value=="") {
        sf_password2.innerHTML = 'Du m&aring;ste ange ett l&ouml;senord.';
        password2.style.border=border_style;
        return false;
    }
    if (name.value=="") {
        document.getElementById('sf_name').innerHTML = 'Du m&aring;ste ange ditt namn.';
        name.style.border=border_style;
        return false;
    }
    if (email.value=="") {
        document.getElementById('sf_email').innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        return false;
    }
    if (password1.value != password2.value) {
        sf_password2.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord tv&aring; g&aring;nger.';
        password2.style.border=border_style;
        return false;
    }
    return true;
}

else-if-satserna kan du ersätta med vanliga if-satser eftersom du har return-satser i dem.

Istället för att initialisera variablerna med elementens värde, skulle jag spara undan en referens till objekten. Då slipper du hämta objektreferenserna på nytt längre ned och kan istället använda deras value-egenskap.

style.border-värdet kan du spara undan i en gemensam variabel i början. Skulle du i framtiden vilja ändra värdet behöver du bara göra det på ett ställe.

Red./ Tydligen infördes några ovälkomna mellanslag i deklarationen av 'border_style'.

Medlem sedan sep. 20026 425 inlägg
#3

Mycket snyggare, tack! (y)
Finns det fler förbättringar att göra? :)

Medlem sedan dec. 20025 483 inlägg
#4

När du kollar innehållet i de olika fälten (.value=="") hindrar det ju ingen från att skriva i exempelvis ett mellanslag och komma undan med det. Men det kanske inte har så stor betydelse?

Medlem sedan sep. 20026 425 inlägg
#5

Det är så sant så sant det, PeterS. Ibland undrar man hur man lyckas missa de mest grundläggande sakerna. :) Här kommer i alla fall scriptet i reviderad version.
Har man inte fyllt i ett formulärfält rätt så markeras det rött och felmeddelande skrivs ut. När man fyllt i det korrekt och skickar iväg formuläret så avmarkeras det röda och felmeddelandet tas bort.

function vali(){

    var username,password1,password2,name,email,sf_password2,border_style;
    
    username = document.getElementById("f_username");
    password1 = document.getElementById("f_password1");
    password2 = document.getElementById("f_password2");
    name = document.getElementById("f_name");
    email = document.getElementById("f_email");
    sf_password2 = document.getElementById("sf_password2");
    border_style = "solid 3px #c00";
    border_style_normal = "";
    
    if (username.value.length < 2) {
        document.getElementById('sf_username').innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn som &auml;r minst tv&aring; tecken l&aring;ngt.';
        username.style.border=border_style;
        return false; }
    else {
        username.style.border=border_style_normal;
        document.getElementById('sf_username').innerHTML='';
        return true; }
    
    if (password1.value.length < 6) {
        document.getElementById('sf_password1').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord p&aring; minst sex tecken.';
        password1.style.border=border_style;
        return false; }
    else {
        password1.style.border=border_style_normal;
        document.getElementById('sf_password1').innerHTML='';
        return true; }
    
    if (password2.value.length < 6 || password1.value != password2.value) {
        sf_password2.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord h&auml;r, minst sex tecken.';
        password2.style.border=border_style;
        return false; }
    else {
        password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML='';
        return true; }
    
    if (name.value.length < 2) {
        document.getElementById('sf_name').innerHTML = 'Du m&aring;ste ange ditt namn.';
        name.style.border=border_style;
        return false; }
    else {
        name.style.border=border_style_normal;
        document.getElementById('sf_name').innerHTML='';
        return true; }
        
    if (email.value.length < 5) {
        document.getElementById('sf_email').innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        return false; }
    else {
        email.style.border=border_style_normal;
        document.getElementById('sf_email').innerHTML='';
        return true; }
        
    if (password1.value != password2.value) {
        sf_password2.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord tv&aring; g&aring;nger.';
        password2.style.border=border_style;
        return false; }
    else {
        sf_password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML='';
        return true; }
        
}

Åsiker och synpunkter? :)

Medlem sedan jan. 20023 327 inlägg
#6

Söderlund, har du lust att visa hur du skriver ut felmeddelandena i html-dokumentet? Intresserad av att använda en lösning liknande din. Visa gärna ett forumlär, uppskattas :)

Medlem sedan sep. 20026 425 inlägg
#7

Så här ser formuläret ut:

<form id="container" method="post" onsubmit="return vali();" runat="server">
<fieldset>
	<legend>Medlemsinfo</legend>
	<p><label for="f_username">Anv&auml;ndarnamn</label>
	<br /><input type="text" id="f_username" name="f_username" tabindex="1" size="20" runat="server" /><span id="sf_username"></span>
	<br /><em>(minst 2 tecken)</em></p>

	<p><label for="f_password1">L&ouml;senord</label>
	<br /><input type="password" id="f_password1" name="f_password1" tabindex="2" size="20" runat="server" /><span id="sf_password1"></span>
	<br /><em>(minst 6 tecken)</em></p>
	<p><label for="f_password2">L&ouml;senord igen</label>
	<br /><input type="password" id="f_password2" name="f_password2" tabindex="3" size="20" runat="server" /><span id="sf_password2"></span>
	<br /><em>(minst 6 tecken)</em></p>
</fieldset>

<fieldset>
	<legend>Personinfo</legend>
	<p><label for="f_name">Namn</label>
	<br /><input type="text" id="f_name" name="f_name" tabindex="4" size="25" runat="server" /><span id="sf_name"></span></p>
	
	<p><label for="f_email">E-postadress</label>
	<br /><input type="text" id="f_email" name="f_email" tabindex="5" size="25" runat="server" /><span id="sf_email"></span></p>
</fieldset>

<p><asp:button id="f_reg" onclick="reg" tabindex="6" text="Registrera mig" runat="server" /></p>
</form>

runat="server" samt <asp:button> är asp.net-specifikt. <asp:button> är en <input type="submit">-knapp. :)

Själva felmeddelandet för aktuellt fält skrivs ut i span-elementet bredvid fältet.

Medlem sedan jan. 20023 327 inlägg
#8

Tack för det Söderlund :)
Det är bara javascript som jag inte är så skillad på, det andra funkar bra. Nu har jag något att inspireras av när jag ska göra validering på klientsidan.

Medlem sedan jan. 20023 327 inlägg
#9

Din senaste ändring med else vilkor för varje validering gör att det formulär retunerar true bara genom att fylla i första fältet korrekt. Jag skulle nog ha en enskild flagga för varje formulärfält och en gemensam flagga för alla, som sätts till true först när alla formulärfält gått igenom valideringen.

En annan förbättring skulle vara att du visar alla felmeddelanden på en gång och inte ett i taget.

Jag ska kolla på det själv och om jag är snabbare så postar jag min lösning här ;)

Medlem sedan sep. 20026 425 inlägg
#10

Compusa: jag upptäckte mitt fel tidigare idag. Tack för vassa ögon ändå! :)

Så här ser javascriptet ut för tillfället:

function vali(){

    var username,password1,password2,name,email,sf_password2,border_style;
    
    username = document.getElementById("f_username");
    password1 = document.getElementById("f_password1");
    password2 = document.getElementById("f_password2");
    name = document.getElementById("f_name");
    email = document.getElementById("f_email");
    sf_password2 = document.getElementById("sf_password2");
    border_style = "solid 3px #c00";
    border_style_normal = "solid 1px #666";
    
    if (username.value.length < 2) {
        document.getElementById('sf_username').innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn som &auml;r minst tv&aring; tecken l&aring;ngt.';
        username.style.border=border_style;
        return false; }
    else {
        username.style.border=border_style_normal;
        document.getElementById('sf_username').innerHTML=''; }
    
    if (password1.value.length < 6) {
        document.getElementById('sf_password1').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord p&aring; minst sex tecken.';
        password1.style.border=border_style; }
    else {
        password1.style.border=border_style_normal;
        document.getElementById('sf_password1').innerHTML=''; }
    
    if (password2.value.length < 6 || password1.value != password2.value) {
        sf_password2.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord h&auml;r, minst sex tecken.';
        password2.style.border=border_style;
        return false; }
    else {
        password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML=''; }
    
    if (name.value.length < 2) {
        document.getElementById('sf_name').innerHTML = 'Du m&aring;ste ange ditt namn.';
        name.style.border=border_style;
        return false; }
    else {
        name.style.border=border_style_normal;
        document.getElementById('sf_name').innerHTML=''; }
        
    if (email.value.length < 5) {
        document.getElementById('sf_email').innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        return false; }
    else {
        email.style.border=border_style_normal;
        document.getElementById('sf_email').innerHTML=''; }
        
}
Medlem sedan sep. 20026 425 inlägg
#11

Jag är också inne på att visa alla felmeddelanden tillsammans i stället för ett i taget. För att göra det måste man väl samla ihop formulärfälten det är fel på (i en array), loopa igenom arrayen och sedan skriva ut felen bredvid respektive formulärfält. Jag tittar på det just nu men om någon vill kan den ju hjälpa mig med detta. :)

Medlem sedan jan. 20023 327 inlägg
#12

Du behöver varken en array eller en loop. Min förslagna förbättring. Om du nu trycker på submit utan att fyllt i något fält så får du fram felmeddelanden för alla obligatoriska fält. Test och se :)

Jag har lagt till en ny boolesk variabel "isValid" som sätts till true när den initsieras. Om något felmeddelande hittas så sätts variabeln till false. I slutet av javascriptet har jag en if-sats som bestämmer vad funktionen ska retunera, true eller false.

<script type="text/javascript">
function vali(){

    var username,password1,password2,name,email,sf_password2,border_style, isValid;
    
    username = document.getElementById("f_username");
    password1 = document.getElementById("f_password1");
    password2 = document.getElementById("f_password2");
    name = document.getElementById("f_name");
    email = document.getElementById("f_email");
    sf_password2 = document.getElementById("sf_password2");
    border_style = "solid 3px #c00";
    border_style_normal = "solid 1px #666";
    isValid = true; // variabel to check if the validation was successful
    
    if (username.value.length < 2) {
        document.getElementById('sf_username').innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn som &auml;r minst tv&aring; tecken l&aring;ngt.';
        username.style.border=border_style;
        isValid = false; }
    else {
        username.style.border=border_style_normal;
        document.getElementById('sf_username').innerHTML=''; }
    
    if (password1.value.length < 6) {
        document.getElementById('sf_password1').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord p&aring; minst sex tecken.';
        password1.style.border=border_style;
        isValid = false; }
    else {
        password1.style.border=border_style_normal;
        document.getElementById('sf_password1').innerHTML=''; }
    
    if (password2.value.length < 6 || password1.value != password2.value) {
        sf_password2.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord h&auml;r, minst sex tecken.';
        password2.style.border=border_style;
        isValid = false; }
    else {
        password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML=''; }
    
    if (name.value.length < 2) {
        document.getElementById('sf_name').innerHTML = 'Du m&aring;ste ange ditt namn.';
        name.style.border=border_style;
        isValid = false; }
    else {
        name.style.border=border_style_normal;
        document.getElementById('sf_name').innerHTML=''; }
        
    if (email.value.length < 5) {
        document.getElementById('sf_email').innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        isValid = false; }
    else {
        email.style.border=border_style_normal;
        document.getElementById('sf_email').innerHTML=''; }
        
    if (password1.value != password2.value) {
        sf_password2.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord tv&aring; g&aring;nger.';
        password2.style.border=border_style;
        isValid = false; }
    else {
        sf_password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML=''; }
    
    if (!isValid) { // Check if the variabel was affected by the validation
        return false;
    }
    else {
        return true;
    }
        
}
</script>
Medlem sedan sep. 20026 425 inlägg
#13

Fan vad gött. Du kollar dock lösenordsfälten två ggr i din kod. Så här ser den korrekta versionen ut:

function vali(){

    var username,password1,password2,name,email,sf_password2,border_style,isValid;
    
    username = document.getElementById("f_username");
    password1 = document.getElementById("f_password1");
    password2 = document.getElementById("f_password2");
    name = document.getElementById("f_name");
    email = document.getElementById("f_email");
    border_style = "solid 3px #c00";
    border_style_normal = "solid 1px #666";
    isValid = true;
    
    if (username.value.length < 2) {
        document.getElementById('sf_username').innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn som &auml;r minst tv&aring; tecken l&aring;ngt.';
        username.style.border=border_style;
        isValid = false; }
    else {
        username.style.border=border_style_normal;
        document.getElementById('sf_username').innerHTML=''; }
    
    if (password1.value.length < 6) {
        document.getElementById('sf_password1').innerHTML = 'Du m&aring;ste ange ett l&ouml;senord p&aring; minst sex tecken.';
        password1.style.border=border_style;
        isValid = false; }
    else {
        password1.style.border=border_style_normal;
        document.getElementById('sf_password1').innerHTML=''; }
    
    if (password2.value.length < 6 || password1.value != password2.value) {
        document.getElementById('sf_password2').innerHTML = 'Du m&aring;ste ange samma l&ouml;senord h&auml;r, minst sex tecken.';
        password2.style.border=border_style;
        isValid = false; }
    else {
        password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML=''; }
    
    if (name.value.length < 2) {
        document.getElementById('sf_name').innerHTML = 'Du m&aring;ste ange ditt namn.';
        name.style.border=border_style;
        isValid = false; }
    else {
        name.style.border=border_style_normal;
        document.getElementById('sf_name').innerHTML=''; }
        
    if (email.value.length < 5) {
        document.getElementById('sf_email').innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        isValid = false; }
    else {
        email.style.border=border_style_normal;
        document.getElementById('sf_email').innerHTML=''; }
          
    if (!isValid) {
        return false;
    }
    else {
        return true;
    }
        
}

Finns det några förbättringar att göra nu? Är tanken med att fånga in alla errors i en array och sedan loopa igenom den för att skriva ut felmeddelanden och markera fält en god tanke? Snyggare lösning än denna?

Medlem sedan jan. 20023 327 inlägg
#14

Den lösningen jag gjorde är definitivt effektivare och snabbare än att loopa och böka med en array. :)

Medlem sedan sep. 20026 425 inlägg
#15

Dåså! Tack för din lösning Compusa. (y) Ska pilla lite till, kom gärna med fler synpunkter!

Medlem sedan jan. 20023 327 inlägg
#16

m_soderlund skrev:

Dåså! Tack för din lösning Compusa. (y) Ska pilla lite till, kom gärna med fler synpunkter!

Tack själv, vi verkar söka ett script med ungefär som funktionalitet :)

Har gjort lite småändringar i koden :bire

function vali(){

    // Variabel declarations
    var username,password1,password2,name,email,sf_password2,border_style;
    var usernameError, password1Error, password2Error, nameError, emailError;
    var isValid;

    // Form fields
    username = document.getElementById("f_username");
    password1 = document.getElementById("f_password1");
    password2 = document.getElementById("f_password2");
    name = document.getElementById("f_name");
    email = document.getElementById("f_email");
    
    
    // Error widgets
    usernameError = document.getElementById('sf_username');
    password1Error = document.getElementById('sf_password1');
    password2Error = document.getElementById("sf_password2");
    nameError = document.getElementById('sf_name');
    emailError = document.getElementById('sf_email');

    // Validation flag
    isValid = true;

    // CSS properties
    border_style = "solid 3px #c00";
    border_style_normal = "solid 1px #666";
    
    // Validate the input
    if (username.value.length < 2) {
        usernameError.innerHTML = 'Du m&aring;ste fylla i ett anv&auml;ndarnamn som &auml;r minst tv&aring; tecken l&aring;ngt.';
        username.style.border=border_style;
        isValid = false; 
    }
    else {
        username.style.border=border_style_normal;
        document.getElementById('sf_username').innerHTML=''; 
    }
    
    if (password1.value.length < 6) {
        password1Error.innerHTML = 'Du m&aring;ste ange ett l&ouml;senord p&aring; minst sex tecken.';
        password1.style.border=border_style;
        isValid = false; 
    }
    else {
        password1.style.border=border_style_normal;
        document.getElementById('sf_password1').innerHTML=''; 
    }
    
    if (password2.value.length < 6 || password1.value != password2.value) {
        password2Error.innerHTML = 'Du m&aring;ste ange samma l&ouml;senord h&auml;r, minst sex tecken.';
        password2.style.border=border_style;
        isValid = false; 
    }
    else {
        password2.style.border=border_style_normal;
        document.getElementById('sf_password2').innerHTML='';  // Den här går kanske att binda till en variabel?
    }
    
    if (name.value.length < 2) {
        nameError.innerHTML = 'Du m&aring;ste ange ditt namn.';
        name.style.border=border_style;
        isValid = false; 
    }
    else {
        name.style.border=border_style_normal;
        document.getElementById('sf_name').innerHTML=''; 
    }
        
    if (email.value.length < 5) {
        emailError.innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        isValid = false; 
    }
    else {
        email.style.border=border_style_normal;
        document.getElementById('sf_email').innerHTML=''; 
    }

    // Final check true or false muuhahah ;)
    if (!isValid) {
        return false;
    }
    else {
        return true;
    }
        
}

Jag hojtar om jag lägger till någon mer funktion...

Medlem sedan sep. 20026 425 inlägg
#17

Mycket snyggt! Tror det blir till att acceptera slutgiltigt svar här. ;)

Vad har du för bakgrund i javascript, Compusa?

Medlem sedan jan. 20023 327 inlägg
#18

Jag har knappt någon bakgrund alls i javascript men jag har erfarenheter av en drös andra programmeringspråk med liknande syntax.

En lite förbättring av email-valideringen, denna hittade jag på google :D

    if ((str.indexOf(".") > 2) && (str.indexOf("@") > 0)) {
        emailError.innerHTML = 'Du m&aring;ste ange en e-postadress.';
        email.style.border=border_style;
        isValid = false; 
    }

Det bästa är naturligtvis att använda regexp men det skulle jag spara till serversidan. Nu går det inte att fuska lika mycket som innan och det besparar nog servern på lite kraft.

Tack för att du delade med dig av ditt script, föredrar denna lösning istället för felmeddelanden som visas med alert-boxar :)

En sista sak jag kom att tänka på och som bör förbättras är att du inte validerar sådant som inte ska valideras, om du förstår vad jag menar? Nu kan du inte återanvända detta script på ett formulär som inte är identiskt. En check eller utökning i funktionaliteten bör göras, så att om du inte har ett formulärfält för exempelvis användarnamn då ska inte denna del av javascript-koden köras. Ska ta en titt på detta senare ikväll om jag hinner. Det bästa är nog att ha en gemensam valideringsfunktion för alla sidor.

Medlem sedan sep. 20026 425 inlägg
#19

Jo, jag har funderat på det jag med. Jag funderar på att göra så här i javascript-koden:

1. Deklarera alla fält som finns i formulär på mina sidor.
2. Markera vilka fält som inte får vara tomma.
3. Markera speciella fält, t.ex. lösenordsfält och e-postfält. Lösenordsfält måste kollas mot varandra och e-postfält bör valideras.
4. Sedan validera alla fält.

Vad sägs om det?

Medlem sedan jan. 20023 327 inlägg
#20

Ja det låter som en bra tanke. Ska sätta mig ner när jag får tid och försöka fundera ut en lösning. :)

Intressant lösning: http://www.xs4all.nl/~sbpoley/webmatters/formval.html

277 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
127 ms — deklarationer (db)
0 ms — hämta statistik (cache)
146 ms — hämta tråd, inlägg och bilagor (db)
127 ms — ändringar (db)