javascript - importar - page header code injection
Personalizar la plantilla dentro de una directiva (4)
Tengo un formulario que usa el marcado de Bootstrap, como el siguiente:
<form class="form-horizontal">
<fieldset>
<legend>Legend text</legend>
<div class="control-group">
<label class="control-label" for="nameInput">Name</label>
<div class="controls">
<input type="text" class="input-xlarge" id="nameInput">
<p class="help-block">Supporting help text</p>
</div>
</div>
</fieldset>
</form>
Hay una gran cantidad de código repetitivo, que me gustaría reducir a una nueva directiva, entrada de formulario, de la siguiente manera:
<form-input label="Name" form-id="nameInput"></form-input>
genera:
<div class="control-group">
<label class="control-label" for="nameInput">Name</label>
<div class="controls">
<input type="text" class="input-xlarge" id="nameInput">
</div>
</div>
Tengo tanto trabajo a través de una plantilla simple.
angular.module(''formComponents'', [])
.directive(''formInput'', function() {
return {
restrict: ''E'',
scope: {
label: ''bind'',
formId: ''bind''
},
template: ''<div class="control-group">'' +
''<label class="control-label" for="{{formId}}">{{label}}</label>'' +
''<div class="controls">'' +
''<input type="text" class="input-xlarge" id="{{formId}}" name="{{formId}}">'' +
''</div>'' +
''</div>''
}
})
Sin embargo, es cuando agrego funciones más avanzadas que me estoy atascando.
¿Cómo puedo admitir valores predeterminados en la plantilla?
Me gustaría exponer el parámetro "tipo" como un atributo opcional en mi directiva, por ejemplo:
<form-input label="Password" form-id="password" type="password"/></form-input>
<form-input label="Email address" form-id="emailAddress" type="email" /></form-input>
Sin embargo, si no se especifica nada, me gustaría usar "text"
predeterminada. ¿Cómo puedo apoyar esto?
¿Cómo puedo personalizar la plantilla en función de la presencia / ausencia de atributos?
También me gustaría poder admitir el atributo "requerido", si está presente. P.ej:
<form-input label="Email address" form-id="emailAddress" type="email" required/></form-input>
Si es required
está presente en la directiva, me gustaría agregarlo a la <input />
generada en la salida e ignorarlo de lo contrario. No estoy seguro de cómo lograr esto.
Sospecho que estos requisitos pueden haber ido más allá de una plantilla simple, y deben comenzar a usar las fases de precompilación, pero no sé por dónde empezar.
Desafortunadamente, las respuestas anteriores no funcionan del todo. En particular, la etapa de compilación no tiene acceso al ámbito, por lo que no puede personalizar el campo en función de los atributos dinámicos. El uso de la etapa de vinculación parece ofrecer la mayor flexibilidad (en términos de creación asíncrona de dom, etc.) El enfoque a continuación aborda lo siguiente:
<!-- Usage: -->
<form>
<form-field ng-model="formModel[field.attr]" field="field" ng-repeat="field in fields">
</form>
// directive
angular.module(''app'')
.directive(''formField'', function($compile, $parse) {
return {
restrict: ''E'',
compile: function(element, attrs) {
var fieldGetter = $parse(attrs.field);
return function (scope, element, attrs) {
var template, field, id;
field = fieldGetter(scope);
template = ''..your dom structure here...''
element.replaceWith($compile(template)(scope));
}
}
}
})
He creado una esencia con un código más completo y una writeup del enfoque.
Esto es lo que terminé usando.
Soy muy nuevo en AngularJS, por lo que me encantaría ver soluciones mejores / alternativas.
angular.module(''formComponents'', [])
.directive(''formInput'', function() {
return {
restrict: ''E'',
scope: {},
link: function(scope, element, attrs)
{
var type = attrs.type || ''text'';
var required = attrs.hasOwnProperty(''required'') ? "required=''required''" : "";
var htmlText = ''<div class="control-group">'' +
''<label class="control-label" for="'' + attrs.formId + ''">'' + attrs.label + ''</label>'' +
''<div class="controls">'' +
''<input type="'' + type + ''" class="input-xlarge" id="'' + attrs.formId + ''" name="'' + attrs.formId + ''" '' + required + ''>'' +
''</div>'' +
''</div>'';
element.html(htmlText);
}
}
})
Ejemplo de uso:
<form-input label="Application Name" form-id="appName" required/></form-input>
<form-input type="email" label="Email address" form-id="emailAddress" required/></form-input>
<form-input type="password" label="Password" form-id="password" /></form-input>
Intenté usar la solución propuesta por Misko, pero en mi situación, algunos atributos, que debían fusionarse en mi plantilla html, eran ellos mismos directivas.
Lamentablemente, no todas las directivas a las que hace referencia la plantilla resultante funcionaron correctamente. No tuve tiempo suficiente para sumergirme en el código angular y descubrir la causa raíz, pero encontré una solución que podría ser útil.
La solución fue mover el código, que crea la plantilla html, desde la compilación a una función de plantilla. Ejemplo basado en el código de arriba:
angular.module(''formComponents'', [])
.directive(''formInput'', function() {
return {
restrict: ''E'',
template: function(element, attrs) {
var type = attrs.type || ''text'';
var required = attrs.hasOwnProperty(''required'') ? "required=''required''" : "";
var htmlText = ''<div class="control-group">'' +
''<label class="control-label" for="'' + attrs.formId + ''">'' + attrs.label + ''</label>'' +
''<div class="controls">'' +
''<input type="'' + type + ''" class="input-xlarge" id="'' + attrs.formId + ''" name="'' + attrs.formId + ''" '' + required + ''>'' +
''</div>'' +
''</div>'';
return htmlText;
}
compile: function(element, attrs)
{
//do whatever else is necessary
}
}
})
angular.module(''formComponents'', [])
.directive(''formInput'', function() {
return {
restrict: ''E'',
compile: function(element, attrs) {
var type = attrs.type || ''text'';
var required = attrs.hasOwnProperty(''required'') ? "required=''required''" : "";
var htmlText = ''<div class="control-group">'' +
''<label class="control-label" for="'' + attrs.formId + ''">'' + attrs.label + ''</label>'' +
''<div class="controls">'' +
''<input type="'' + type + ''" class="input-xlarge" id="'' + attrs.formId + ''" name="'' + attrs.formId + ''" '' + required + ''>'' +
''</div>'' +
''</div>'';
element.replaceWith(htmlText);
}
};
})