Obtener con JavaScript el valor seleccionado en un webcontrol DropDownList.

Nuevamente con algunos tips para los que les gusta jugar trabajar con JavaScript y los controles web. Algo que preguntan (sea msn, por email, o en los grupos de noticias) es como leer un combo desde JavaScript (el valor o el índice) si dicho combo es un webcontrol

Cuando decimos un webcontrol DropDownList en el servidor porque trabajamos con tecnología ASP.NET, en el cliente se renderiza a popular y conocido HTML control Select.
O sea este sencillo combo (enlazado a un objeto)

<asp:DropDownList ID="ddlCategorias" runat="server" DataSourceID="objDSCategorias"
        DataTextField="CategoryName" DataValueField="CategoryID">

En el cliente se renderiza en el cliente (con datos incluidos)
<select name="ctl00$Contentplaceholder1$ddlCategorias" 
        id="ctl00_Contentplaceholder1_ddlCategorias">
   <option value="1">Beverages 1234</option>
   <option value="2">Condiments 2</option>
   <option value="3">Confections</option>
   <option selected="selected" value="4">Dairy Products</option>
   <option value="5">Grains/Cereals</option>
   <option value="6">Meat/Poultry</option>
   <option value="7">Produce</option>
   <option value="8">Seafood</option>
</select>

Como se lee el ID en el navegador del cliente esta compuesto por una concatenación de contenedores de donde esta finalmente el webcontrol, en este caso esta dentro de un ContentPlaceHolder, pero podría estar sucesivamente dentro de Panel u otros controles contenedores… por eso no sabemos de "antemano" cual es el ID para hacer referencia en JavaScript.

Asignar una función JavaScript. Asociar eventos clientes en controles del servidor


Deseamos ejecutar una función js cuando el en cliente se realiza un evento onChange del control.

Por ejemplo si tenemos esta función:

 
<script type="text/javascript" language="javascript">
  
  function Seleccionar(combo){
      var indice = combo.selectedIndex;
      var valor = combo.options[combo.selectedIndex].text;
      alert(indice);
      alert(valor);
      
      //Guardamos en un hidden
      document.getElementById('<%=HiddenField1.ClientId%>').value = valor;
  }
  </script>
 
Que para economizar estamos enviado el objeto select en un parametro combo, entonces ya lo conocemos y no tenemos necesidad de realizar un getElementById.

En el cliente se deberia escribir asi:

   

<select id="ejemplo" onChange="Seleccionar(this);">
 
Como logramos esto desde el codebehind?

Debemos escribir un atributo en el webcontrol
ddlCategorias.Attributes.Add("onChange", "Seleccionar(this);")
o asi:
ddlCategorias.Attributes("onChange") = "Seleccionar(this);"
Ok… ya tenemos nuestro evento en el control… y lo testeamos 😉
image
image
 
Un tips mas, tenemos un nuevo requerimiento:
Asignar este valor a un campo oculto

Tendríamos que obtener el control del campo oculto en javascript y lo hacemos mediante la busqueda en el documento con getElementById, pero no sabemos de antemano cual es el Id del cliente, entonces debemos escribirlo de la siguiente manera:
document.getElementById('<%=HiddenField1.ClientId%>').value = valor;
Donde hacemos uso de la propiedad .ClientId

Enlaces

Maxlength en Textbox Multiline. Limitar la cantidad de caracteres, validar y simular Maxlength

Cuando uno se adentra al mundo web directamente de mundo SmartClient (VB6, winforms) sin pasar antes por conocimiento de HTML, programar en ASP.NET no sea del todo razonable y lógico como diría Sr. Spock. Me preguntaba un amigo (y también en los grupos de noticias de asp.net) como validar un texbox multilinea con la propiedad Maxlength, más precisamente era un pedido de auxilio porque "no funcionaba"!

Vamos a un poco de logica difusa jee!, veamos un poco de renderizado en HTML de nuestros queridos controles Texbox SingleLine y Multiline

<asp:TextBox ID="txtSingleLine" runat="server" MaxLength="10"></asp:TextBox>
<asp:TextBox ID="txtMultiline" runat="server" MaxLength="10" TextMode="MultiLine"></asp:TextBox>
 
Se renderizan…
<input name="ctl00$txtSingleLine" type="text" value="" maxlength="10" id="ctl00_txtSingleLine" /> 
<textarea name="ctl00$txtMultiline" rows="2" cols="20" id="ctl00_txtMultiline"></textarea>
 
Aquí vemos dos cotroles HTML uno es un input del tipo text y el otro un textarea.

A propósito coloque de antemano la propiedad Maxlength del webcontrol Textbox pero solo lo renderiza en el control HTML correcto que es el en input

Aqui es el navegador quien utiliza esta propiedad/atributo del control para no permitir mas contenido que el especificado. Pero en cambio en el textarea no lo tenemos.. entonces que hacemos?

 

Como simular Maxlength en Texbox Multiline

Hasta ahora vemos que en el cliente tenemos un control HTML texarea, pero como restringir que el usuario solo pueda ingresar una cantidad de caracteres predefinidos o incluso validar este ingreso, vemos una serie de opciones que nos pueden ayudar

  1. Con Regular Expression Validator
  2. Con Custom Validator
    1. desde el servidor (con funcion en codebehind)
    2. en el cliente (con funcion js)
  3. Con Script js (sin controles de validación)
  4. Simular la propiedad Maxlength en el texarea/textbox multiline

 

OPCION 1: Regular Expression Validator

Haciendo uso de los controles de validación podemos validar en el cliente mediante expresiones regulares (que ese lenguaje para describir patrones de texto que muchas veces uno cree que lo hizo un Vulcano)

Ejemplo sencillo:

<asp:RegularExpressionValidator ID="revTexbox3" runat="server"             
       ErrorMessage="Debe ingresar hasta un maximo de 10 caracteres"            
       ValidationExpression="^([Ss]{0,10})$"             
       ControlToValidate="TextBox3"            
       Display="Dynamic"></asp:RegularExpressionValidator>

Las expresiones regulares son muy potentes pero se vuelven muy complejas… (solo el que la formulo a veces la entiende)

Por ejemplo si queremos solo numeros necesitariamos algo asi "^([d]{0,10})$"
Algunos Enlaces:
 

OPCION 2: Custom Validator

Aquí podemos utilizar tanto con código del lado del servidor como en el cliente (javascript)

2.1: Validar en el servidor, es decir en el postback se validará

<asp:CustomValidator ID="cvTexbox4" runat="server"             
      ErrorMessage="Debe ingresar hasta un maximo de 10 caracteres"            
      ControlToValidate="txtEjemplo4"></asp:CustomValidator>

 
y en el codebehind… un ejemplo simple
Protected Sub cvTexbox4_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles cvTexbox4.ServerValidate
Dim cantidadCaracteres As Integer = args.Value.Length
If cantidadCaracteres > 10 Then
args.IsValid = False
Else
args.IsValid = True
End If
End Sub

2.1: Validar en el cliente, seteando la propiedad ClientValidationFunction con la función js

Tenemos la definición del customvalidator

<asp:CustomValidator ID="CustomValidator1" runat="server" 
ErrorMessage="Debe ingresar hasta un maximo de 10 caracteres"
ClientValidationFunction="ValidarTextoCantidad"
ControlToValidate="txtEjemplo5"></asp:CustomValidator>

 
La funcion js seria similar a esto
<script language="javascript" type="text/javascript">
function ValidarTextoCantidad(source, arguments){
var maxlength = 10;
if (arguments.Value.length==maxlength) {
arguments.IsValid=true
}else{
arguments.IsValid=false
}
}
</script>

 
 
 

OPCION 3: Mediante script JS (son controles de validación de ASP.NET)

Aquí tenemos un textbox multiline para agregarle eventos de JS y disparar una función

<asp:TextBox ID="txtEjemplo6" runat="server" 
Height="88px" TextMode="MultiLine" Width="269px"></asp:TextBox>

 
Luego la funcion js, simple y dejo al criterio de cada uno agregar las acciones mas personalizadas, aqui solo presentamos un "molesto mensaje" y tambien "cortamos" el exceso de caracteres. Muy dictador
 
<script language="javascript" type="text/javascript">
function ValidarCaracteres(textareaControl,maxlength){

if (textareaControl.value.length > maxlength){
textareaControl.value = textareaControl.value.substring(0,maxlength);
alert("Debe ingresar hasta un maximo de "+maxlength+" caracteres");
}
}
</script>

Y como asociamos este js en los ventos onKeypress y onKeyUp ?

txtEjemplo6.Attributes.Add("onkeypress", " ValidarCaracteres(this, 10);")
txtEjemplo6.Attributes.Add("onkeyup", " ValidarCaracteres(this, 10);")

Logrando así que se dispare la función ValidarCaracteres cuando la necesitamos

 

OPCION 4: Simuladores…

Escribir realmente la propiedad Maxlength :)  "simular la propiedad maxlength"

Este script me gusto por la idea, pero bueno no es del todo "valido" el HTML que hay que generar… pero esta bueno, veamos como funciona

(lo encontre aquí: http://www.quirksmode.org/dom/maxlength.html)

Necesitamos agregar al html control renderizado la propiedad que "no viene de fabrica" ;), que es maxlength, quedando así en el cliente:

<textarea id="text" name="text" maxlength="10"></textarea>

 
Como hacemos para agregar esta propiedad? Bien como en el paso 3 agregamos propiedades/atributos para generar eventos en js aqui lo mismo.
Teniendo un textbox en diseño simple:
 
<asp:TextBox ID="txtEjemplo7" runat="server" 
Height="88px" TextMode="MultiLine" Width="269px"></asp:TextBox>

Agregamos el atributo que necesitamos
 
txtEjemplo7.Attributes.Add("maxlength", "10")

Hasta ahora se renderiza con un atributo que "no es legal" pero nos puede servir gracias a este script ingenioso
<script language="javascript" type="text/javascript">
function setMaxLength() {
var x = document.getElementsByTagName('textarea');
var counter = document.createElement('div');
counter.className = 'counter';
for (var i=0;i<x.length;i++) {
if (x[i].getAttribute('maxlength')) {
var counterClone = counter.cloneNode(true);
counterClone.relatedElement = x[i];
counterClone.innerHTML = '<span>0</span>/'+x[i].getAttribute('maxlength');
x[i].parentNode.insertBefore(counterClone,x[i].nextSibling);
x[i].relatedElement = counterClone.getElementsByTagName('span')[0];

x[i].onkeyup = x[i].onchange = checkMaxLength;
x[i].onkeyup();
}
}
}

function checkMaxLength() {
var maxLength = this.getAttribute('maxlength');
var currentLength = this.value.length;
if (currentLength > maxLength)
this.relatedElement.className = 'toomuch';
else
this.relatedElement.className = '';
this.relatedElement.firstChild.nodeValue = currentLength;
// not innerHTML
}
</script>

Ok.. pero donde lo llamo? y como?
Hay que agregarlo en el load de la pagina, es decir en el evento onload del body HTML
Y en ASP.NET como hago para generar este evento?
Primeramente tienes que convertir el tag body en  un html control de asp.net… esto es simplemente agregar la propiedad runat="server" y también un identificador para poder accesarlo desde el codebehind
Vamos a nuesta pagina o al master y agregamos:
 
<body runat="server" id="body1">

 
Y desde la pagina donde necesitamos que este script se ejecute
 
Dim body1 As HtmlControl = Me.Master.FindControl("body1")
body1.Attributes.Add("onload", "setMaxLength();")

Y listo.. tenemos algo asi
image
Además nos agrega luego del textarea unas etiquetas para que el usuario visualice la cantidad de caracteres permitidos y los ingresados.

 

Descargar ejemplo

(si no puedes ver el enlace click aquí para descargar)

Espero que te sirva de ayuda o guía.

 

 

Enlaces:

Architecture Journal Reader

Servicios + Servicios, y para muestra basta un botón…
Ingresando a la web de The Architecture Journal, me encuentro con una software beta el Architecture Journal Reader (Beta) para la lectura offline de este recomendable boletín.

image

Soporte para Win2003,Vista, XP… y utiliza WPF (pero el mismo instalador se encarga de notificarnos si no tenemos .NET 3.0)

Al principio me dije se instalo mal.. pero porque no me daba ningún indicio que estaba realizando alguna tarea

image

Pero realmente estaba descargando, luego de un tiempo "al usuario" (o sea me dio una alegria algo estaba ocurriendo)

image

image  .. y luego de 55min. image 
Creo que mi conexión no es del todo fast and furious ;(

Y al finalizar (luego de unos 75min) image   ups!

image

 

Pero bueno.. no tenia el el valor del ultimo update pero algo descargo.. selecciono el idioma y aquí la interfaz WPF in action

image

y en cada articulo podremos tener "usabilidad"

image

Y lo que ya nos acostumbraron otros ejemplos en WPF… anotaciones online sobre el texto (anotacion de Ink Note, o puro texto)

image

 

Todavía no utilice a fondo WPF pero me gusta la parte de imágenes como se "ajusta a las columnas" dependiendo de tamaño del texto

image

 

image

 

Ya vimos el ejemplo similar el New York Times Reader 

Me gusto mucho poder leer desde esta plataforma (a parte que tenemos el Architecture Journal Reader en formato pdf o que nos envien en papel a nuestro domicilio)

 

 

Enlaces

+ Usabilidad. Gmail color para etiquetas

Soy un "adicto a las etiquetas" de Gmail, me ayudan a organizar, encontrar y mas aun "ocultar" 🙂 la información; y mas cuando estoy suscripto a varios newsletters, grupos de noticias por email (casi nadie usa los NNTP, o lo usamos vía Google Grupos)

Que hay de nuevo?

Me encontre esta mañana con algo que "necesitaba pero no lo pedía" como tantas cosas que queremos en la vida "color for labels" es decir literalmente colores para etiquetas

Miremos

GmailColorEtiquetas001

Seleccionamos el color que deseamos (no se porque no utilizaron algo parecido a este ColorPicker)

GmailColorEtiquetas002

Y lo tenemos un lindo "enjambre" de colores en nuestra bandeja de entrada (que podemos solucionar archivando los correos con filtros)

 GmailColorEtiquetas003

 

PD: Ya se nos esta cargando la interfaz…. pero no nos damos cuenta no? 😉
PD2: Por el momento solo en la versión en ingles.