Lorenzo Gonzalez Gascón
I'm teacher in computer Science in a high school, the high school is named "CIPFP Mislata" in Spain-Valencia-Mislata .
Lorenzo González
lorenzo.profesor arroba gmail.com
@logongas
http://cursoangularjs.es
CIPFP Mislata en Valencia
¿Quieres que mis alumnos hagan las prácticas en tu empresa?
¡Ponte en contacto conmigo!
y
Crear una directiva "date-picker" en el módulo "jquery-ui"
Crear otra directiva "date-picker" en el módulo "bootstrap"
angular.
module("jquery-ui").
directive("date-picker",function() {
});
angular.
module("bootstrap").
directive("date-picker",function() {
});
<input date-picker >
angular.module("app",["jquery-ui"]);
Cargamos el módulo de "jquery-ui"
Usamos la directiva "date-picker"
angular.module("app",["bootstrap"]);
Cargamos el módulo de "bootstrap"
Usamos la directiva "date-picker"
<input date-picker >
<input date-picker="yy-mm-dd" >
yy : Año con 4 dígitos
mm : Mes con 2 dígitos
dd : Día con 2 dígitos
<input date-picker="yyyy-MM-dd" >
yyyy : Año con 4 dígitos
MM : Mes con 2 dígitos
dd : Día con 2 dígitos
<input ng-model="persona.fechaNacimiento" date-picker="yyyy-MM-dd" >
<input ng-model="movimiento.fechaCreacion" date-picker="yyyy-MM-dd" >
<input ng-model="titulado.fechaInscripcion" date-picker="yyyy-MM-dd" >
<input ng-model="cuenta.fechaActualizacion" date-picker="yyyy-MM-dd" >
<input ng-model="cambio.fechaAplicacion" date-picker="yyyy-MM-dd" >
Si siempre va a ser el mismo formato de fecha a lo largo de todo el proyecto, una solución es:
app.constant("datePickerConfig",{
format:"MM-dd-yyyy"
});
Se define el formato por defecto con una constante
app.config(function(datePickerConfig) {
datePickerConfig.format("yyyy-MM-dd");
});
<input ng-model="persona.fechaNacimiento" date-picker >
<input ng-model="movimiento.fechaCreacion" date-picker >
<input ng-model="titulado.fechaInscripcion" date-picker >
<input ng-model="cuenta.fechaActualizacion" date-picker >
<input ng-model="cambio.fechaAplicacion" date-picker >
<input ng-model="persona.fechaNacimiento" date-picker >
<input ng-model="movimiento.fechaCreacion" date-picker >
<input ng-model="titulado.fechaInscripcion" date-picker="dd/MM/yyyy" >
<input ng-model="cuenta.fechaActualizacion" date-picker >
<input ng-model="cambio.fechaAplicacion" date-picker >
<input date-picker spanish-format >
app.directive("spanishFormat", [function () {
return {
compile: function (tElement, tAttrs) {
tAttrs.datePicker="dd/mm/yyyy";
}
};
}]);
app.directive("spanishFormat", [function () {
return {
compile: function (tElement, tAttrs) {
return {
pre: function (scope, iElement, iAttrs, controller, transcludeFn) {
iAttrs.datePicker="dd/mm/yyyy";
},
post: function (scope, iElement, iAttrs, controller, transcludeFn) {
}
};
}
};
}]);
Ahora podríamos hacer la asignación de "iAttrs.datePicker" usando algún valor del Scope o un atributo interpolado
<div class="row">
<div class="span12">
<ng-transclude></ng-transclude>
</div>
</div>
<div class="row">
<div class="col-md-12">
<ng-transclude></ng-transclude>
</div>
</div>
Versión para bootstrap 2
Versión para bootstrap 3
app.constant("bootstrapVersion",2);
Usamos una constante con la versión de bootstrap
app.directive("fila", ['bootstrapVersion',function (bootstrapVersion) {
return {
restrict: "E",
transclude:true,
template: function (tElement, tAttrs) {
var css="";
if (bootstrapVersion===2) {
css="span12";
} else {
css="col-md-12";
}
tpl='<div class="row"><div class="' + css + '"><ng-transclude></ng-transclude></div></div>';
return tpl;
}
};
}]);
NOTA: Lo mismo se hace con templateUrl
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
<strong>Aviso</strong>Directiva se personaliza
</div>
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" data-dismiss="alert" style="float:right">Cerrar</button>
<strong>Aviso</strong>Esta directiva se personaliza
</div>
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
<strong>{{tipo}}</strong>{{mensaje}}
</div>
template de la directiva
<alert tipo="Aviso" mensaje="Directiva se personaliza" ></alert>
Usando la directiva
<div class="alert alert-warning alert-dismissible" role="alert">
<close-alert-button></close-alert-button>
<strong>{{tipo}}</strong>{{mensaje}}
</div>
app.directive("closeAlertButtonn", [function () {
return {
restrict: "E",
template: '<button type="button" data-dismiss="alert" style="float:right">Cerrar</button>'
};
}]);
app.directive("defaultCloseAlertButton", [function () {
return {
restrict: "E",
template: '<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span></button>'
};
}]);
El formato del botón es el estándar de bootstrap
var existe=$injector.has('closeAlertButtonDirective');
El método "has" de servicio "$injector" nos permite averiguarlo
NOTA: Al método "has" se le pasa el nombre de la directiva mas el texto "Directive"
template: function () {
var button;
if ($injector.has('closeAlertButtonDirective') === true) {
button = "<close-alert-button></close-alert-button>"
} else {
button = "<default-close-alert-button></default-close-alert-button>"
}
return '<div class="alert alert-warning alert-dismissible" role="alert">' + button + ' <strong>{{tipo}}</strong> {{mensaje}}</div>'
}
El template es distinto dependiendo de si existe o no la directiva "closeAlertButton"
app.directive("directiveName", [function () {
var directiveDefinitionObject = {
template:function (tElement, tAttrs) {
return "";
},
compile: function (tElement, tAttrs) {
return {
pre: function (scope, iElement, iAttrs, controller, transcludeFn) {
},
post: function (scope, iElement, iAttrs, controller, transcludeFn) {
}
};
}
};
return directiveDefinitionObject;
}]);
function (tElement, tAttrs) {
}
<mi-directiva
data-nombre="Lorenzo"
x-apellido="Gonzalez"
mi-ciudad="Valencia"
mi_instituto="Mislata"
></elemento>
tElement.attr("data-nombre") ==> "Lorenzo"
tElement.attr("x-apellido") ==> "Gonzalez"
tElement.attr("mi-ciudad") ==> "Valencia"
tElement.attr("mi_instituto") ==> "Mislata"
Los nombres NO están normalizados
<mi-directiva
data-nombre="Lorenzo"
x-apellido="Gonzalez"
mi-ciudad="Valencia"
mi_instituto="Mislata"
></elemento>
tAttrs.nombre ==> "Lorenzo"
tAttrs.apellido ==> "Gonzalez"
tAttrs.miCiudad ==> "Valencia"
tAttrs.miInstituto ==> "Mislata"
Los nombres SI están normalizados
<elemento mi-directiva="{{nombre}}" ></elemento>
tElement.attr("mi-directiva") ====> "{{nombre}}"
tAttrs.miDirectiva ====> "{{nombre}}"
app.directive("titulo", [function () {
return {
template: "<h1>Esto es el titulo</h1>"
};
}]);
app.directive("subtitulo", [function () {
return {
template: "<h2>Esto es el subtitulo</h2>"
};
}]);
<!-- HTML Original -->
<div titulo>
</div>
<!-- RESULTADO GENERADO -->
<div titulo>
<h1>Esto es el titulo</h1>
</div>
<!-- HTML Original -->
<div subtitulo>
</div>
<!-- RESULTADO GENERADO -->
<div subtitulo>
<h2>Esto es el subtitulo</h2>
</div>
<!-- HTML Original -->
<div titulo subtitulo>
</div>
Error: [$compile:multidir] Multiple directives [subtitulo, titulo] asking for template on: <div titulo="" subtitulo="">
Que las directivas con "template" únicamente
se puedan usar como elementos y de esa forma
que solo pueda haber una
app.directive("titulo", [function () {
return {
restrict: "E",
template: "<h1>Esto es el titulo</h1>"
};
}]);
<titulo></titulo>
app.directive("sinTemplate", [function () {
return {
};
}]);
app.directive("conTemplate", [function () {
return {
template: "<h1>Esto es la plantilla</h1>"
};
}]);
<!-- HTML Original -->
<div sin-template>
<h1>Esto es el contenido</h1>
</div>
<!-- RESULTADO GENERADO -->
<div sin-template>
<h1>Esto es el contenido</h1>
</div>
<!-- HTML Original -->
<div con-template>
<h2>Esto es el contenido</h2>
</div>
<!-- RESULTADO GENERADO -->
<div con-template>
<h1>Esto es la plantilla</h1>
</div>
La directiva ngTransclude nos permite incluir el contenido del elemento en la plantilla de la directiva.
PERO: El scope que se usa no es el de la directiva
app.directive("titulo", [function () {
return {
restrict: "E",
transclude:true,
template: "<div><h1>Esto es la plantilla</h1><ng-transclude></ng-transclude></div>"
};
}]);
app.directive("subtitulo", [function () {
return {
restrict: "E",
template: "<h2>Esto es la directiva subtitulo</h2>"
};
}]);
<!-- HTML Original -->
<titulo>
<subtitulo></subtitulo>
<h2>Esto es el contenido</h2>
</titulo>
<!-- RESULTADO GENERADO -->
<div>
<h1>Esto es la plantilla</h1>
<h2>Esto es la directiva subtitulo</h2>
<h2>Esto es el contenido</h2>
</div>
El contenido puede tener a su vez nuevas directivas, como por ejemplo "subtitulo",
las cuales tambien se compilan
function (tElement, tAttrs) {
return {
pre: function (scope, iElement, iAttrs, controller, transcludeFn) {
},
post: function (scope, iElement, iAttrs, controller, transcludeFn) {
}
};
}
app.directive("entreSemana", [function () {
return {
restrict: "A",
priority:2,
compile: function (tElement, tAttrs) {
tElement.append("<option value='1'>Lunes</option>");
tElement.append("<option value='2'>Martes</option>");
tElement.append("<option value='3'>Miercoles</option>");
tElement.append("<option value='4'>Jueves</option>");
tElement.append("<option value='5'>Viernes</option>");
}
};
}]);
app.directive("finSemana", [function () {
return {
restrict: "A",
priority:1,
compile: function (tElement, tAttrs) {
tElement.append("<option value='6'>Sabado</option>");
tElement.append("<option value='7'>Domingo</option>");
}
};
}]);
<!-- HTML Original -->
Dia de la semana de inicio de codemotion Madrid:
<select ng-model="codemotion.madrid" entre-semana fin-semana ></select>
<!-- RESULTADO GENERADO-->
Dia de la semana de inicio de codemotion Madrid:
<select ng-model="codemotion.madrid" entre-semana fin-semana >
<option value='1'>Lunes</option>
<option value='2'>Martes</option>
<option value='3'>Miercoles</option>
<option value='4'>Jueves</option>
<option value='5'>Viernes</option>
<option value='6'>Sabado</option>
<option value='7'>Domingo</option>
</select>
app.directive("finSemana", [function () {
return {
restrict: "A",
priority:1,
compile: function (tElement, tAttrs) {
tElement.append("<option value='6'>Sabado</option>");
tElement.append("<option ng-style='{backgroundColor:\"red\"}' value='7'>Domingo</option>");
}
};
}]);
Se añade la directiva ng-style para ver si se aplica
<!-- HTML Original -->
Dia de la semana de inicio de codemotion Madrid:
<select ng-model="codemotion.madrid" entre-semana fin-semana ></select>
<!-- RESULTADO GENERADO-->
Dia de la semana de inicio de codemotion Madrid:
<select ng-model="codemotion.madrid" entre-semana fin-semana >
<option value='1'>Lunes</option>
<option value='2'>Martes</option>
<option value='3'>Miercoles</option>
<option value='4'>Jueves</option>
<option value='5'>Viernes</option>
<option value='6'>Sabado</option>
<option value='7' style="background-color: red;">Domingo</option>
</select>
Se ha procesado la directiva ng-style en el nuevo elemento
app.directive("requerido", [function () {
return {
restrict: "A",
compile: function (tElement, tAttrs) {
tAttrs.$set("ngRequired","true");
}
};
}]);
<select
ng-model="codemotion.madrid"
name="madrid"
entre-semana
fin-semana
requerido
></select>
<select
ng-model="codemotion.madrid"
name="madrid"
entre-semana
fin-semana
requerido
ng-required="false"
></select>
function (scope, iElement, iAttrs, controller, transcludeFn) {
}
Empieza por "i" de instance ya que
es la "instancia" del elemento "tElement"
<elemento mi-directiva="{{nombre}}" ></elemento>
iElement.attr("mi-directiva") ====> "{{nombre}}"
iAttrs.miDirectiva ====> "Hola Mundo"
$scope.nombre="Hola Mundo"
app.directive("finSemana", [function () {
return {
restrict: "A",
priority: 1,
compile: function (tElement, tAttrs) {
return {
pre: function (scope, iElement, iAttrs, controller, transcludeFn) {
},
post: function (scope, iElement, iAttrs, controller, transcludeFn) {
iElement.append("<option value='6'>Sabado</option>");
iElement.append("<option ng-style='{backgroundColor:\"red\"}' value='7'>Domingo</option>");
}
}
}
};
}]);
Se añade ng-style para ver si se aplica
<!-- HTML Original -->
Dia de la semana de inicio de codemotion Madrid:
<select ng-model="codemotion.madrid" entre-semana fin-semana ></select>
<!-- RESULTADO GENERADO-->
Dia de la semana de inicio de codemotion Madrid:
<select ng-model="codemotion.madrid" entre-semana fin-semana >
<option value='1'>Lunes</option>
<option value='2'>Martes</option>
<option value='3'>Miercoles</option>
<option value='4'>Jueves</option>
<option value='5'>Viernes</option>
<option value='6'>Sabado</option>
<option value='7'>Domingo</option>
</select>
No se ha procesado la directiva ng-style
scope.codemotion={
madrid:1,
berlin:1,
telAviv:1,
milan:1
}
<div ng-repeat="(campo,valor) in codemotion">
Dia de la semana de inicio de codemotion {{campo}}
<select ng-model="codemotion[campo]" entre-semana fin-semana >
</select>
</div>
<select ng-model="codemotion[campo]" entre-semana fin-semana >
<option value='1'>Lunes</option>
<option value='2'>Martes</option>
<option value='3'>Miercoles</option>
<option value='4'>Jueves</option>
<option value='5'>Viernes</option>
<option value='6'>Sabado</option>
<option value='7'>Domingo</option>
</select>
Se genera este "tag" una única vez y simplemente se clona para cada elemento de la lista
$scope.metadata={};
$scope.metadata.ciudad = {
isArrayObjects: true,
values: [
{toString: "Madrid", pais: "España"},
{toString: "Berlin", pais: "Alemania"},
{toString: "Tel Aviv", pais: "Israel"},
{toString: "Milan", pais: "Italia"},
]
};
$scope.metadata.diaSemana = {
isArrayObjects: false,
values: [
"Lunes","Martes","Miercoles","Jueves","Sabado","Domingo"
]
};
$scope.ciudad;
$scope.diaSemana;
<select
ng-model="ciudad"
ng-options="value as value.toString for value in metadata['ciudad'].values"
></select>
<select
ng-model="diaSemana"
ng-options="value for value in metadata['diaSemana'].values"
></select>
Demasiado código repetido en ng-options a lo largo del proyecto para user el objeto "metadata"
pre: function (scope, iElement, iAttrs, controller, transcludeFn) {
var model=iAttrs.ngModel;
var isArrayObjects = scope.$eval(" metadata['" + model + "'].isArrayObjects");
if (isArrayObjects === true) {
iAttrs.ngOptions = "value as value.toString for value in metadata['" + model + "'].values";
} else {
iAttrs.ngOptions = "value for value in metadata['" + model + "'].values";
}
}
La directiva "ca-options" solo tiene función pre-link
<select ng-model="ciudad" ca-options ></select>
<select ng-model="diaSemana" ca-options ></select>
Queremos eliminar el código repetitivo
Ya que desde ninguna función se pueden añadir directivas al propio elemento
Añadir elementos | Añadir listeners | Acceso al scope | Modificar attrs | Cualquier modificación posterior | Nuevas directivas a la directiva | |
---|---|---|---|---|---|---|
template | - | - | - | - | - | - |
compile | Si y directivas | - | - | Si | - | - |
pre-link | - | Si | Si | Si | - | - |
post-link | Si | Si | Si | - | Si | - |
$compile(iElement)(scope)
$provide.decorator('miDirectivaDirective', function($delegate) {
});
post: function (scope, iElement, iAttrs, controller, transcludeFn) {
}
lorenzo.profesor arroba gmail.com
https://github.com/logongas/codemotion2014
By Lorenzo Gonzalez Gascón
I'm teacher in computer Science in a high school, the high school is named "CIPFP Mislata" in Spain-Valencia-Mislata .