2012-10-03 11 views
6

Tengo una directiva personalizada en angularjs. Básicamente, lo que quiero que suceda es que el usuario elija un valor de un cuadro de selección y eso agregará un valor a un conjunto. Esto hace que mi directiva personalizada sea invocada y represente un nuevo elemento en la pantalla. Quiero que el campo de texto generado por la directiva se vincule con el atributo del controlador.Uso de ng-model dentro de una directiva

HTML

<device-list ng-repeat="device in devices" key="device.key" display-name="device.display_name" bind-prefix="descriptions"></device-list> 

Directiva

angular.module('device_list_tag', []). 
    directive('deviceList', function() { 
    return { 
     restrict: 'E', 
     require: '?ngModel', 
     scope: { 
     devices: '=', 
     key: '=', 
     displayName: '=', 
     bindPrefix: '@' 
     }, 
     link: function(scope, element, attrs) { 

     var deviceListElement = $(element) 
     var containerDiv = $('<div>') 
      .addClass('row') 


     var labelTag = $('<label>').text(scope.displayName) 
      .addClass('span1') 

     var bindField = attrs.bindPrefix+'.'+scope.key 

     var textField = $('<input>') 
      .addClass('span3') 
      .attr('ng-model', bindField) 

     containerDiv.append(labelTag) 
     containerDiv.append(textField) 

     deviceListElement.append(containerDiv) 
     } 
    } 
    }) 

controlador

function DevicesCtrl($scope) { 
    descriptions = {} 
} 

Parece como si como ng-modelo es local al ámbito de la Directiva, ¿cómo puedo hacer que se aplica a las ¿el padre? Si tengo un montón de campos de texto en la página, como

<input ng-model="descriptions.test"/> 

Funciona obras excepto los campos generados por el cuadro de selección.

Respuesta

9

Ok, lo descubrí. Implicaba pasar mi atributo principal como '=' (sugerido por Tosh). También tuve que hacer una llamada a $ compile para que reconozca la directiva ng-model. Aquí está el código completo, estoy seguro de que hay una manera de hacer este limpiador, pero estoy contento de que funcione.

angular.module('device_list_tag', []). 
    directive('deviceList', function($compile) { 
    return { 
     restrict: 'E', 
     scope: { 
     devices: '=', 
     key: '=', 
     displayName: '=', 
     bindAttr: '=' // added 
     }, 
     link: function(scope, element, attrs) { 

     console.log(scope) 

     var deviceListElement = $(element) 
     var containerDiv = $('<div>') 
      .addClass('row') 


     var labelTag = $('<label>').text(scope.displayName) 
      .addClass('span1') 

     var bindField = 'bindAttr.'+scope.key 

     var textField = $('<input>') 
      .addClass('span3') 
      .attr('ng-model', bindField) 

     $compile(textField)(scope) // added 

     containerDiv.append(labelTag) 
     containerDiv.append(textField) 

     deviceListElement.append(containerDiv) 
     } 
    } 
    }) 
+0

¿Por qué no simplemente utiliza un atributo de plantilla en la directiva y lo vincula como lo haría normalmente? P.ej.: template: ' ...' ¿No es esto para lo que está la plantilla o te equivoqué? Como el ejemplo en la parte inferior de la página: http://docs.angularjs.org/guide/directive –

+0

El problema es que no sé el nombre del atributo al que voy a vincular desde dentro de la directiva. Intenté usar una plantilla, pero el problema con el que me topé fue cómo hacer que {{some.random.attribute}} funcionara. – Mike

+0

Me gustaría vincular una variable fija y simplemente actualizar la variable con el valor de algunas.tribuciones aleatorias. Descubrí qué es eso. Por ejemplo, podría configurar una función llamada getSomeRandomAttr (clave) que esté conectada al alcance de sus padres o llame a un servidor. Entonces solo necesita actualizar la variable fija después de llamar a la función. –

2

Puede ser que usted puede agregar bindField: '=' en la definición de directiva de alcance. Y use esta variable para conectarse al alcance principal.

+0

estoy jugando un poco con eso ahora, pero no han podido averiguar cómo "enlazar" la variable al campo de texto. ¿Tienes alguna sugerencia? – Mike

1

¿Usted está pidiendo,

1) Mantener la matriz ámbito primario actualiza, mientras editamos los elementos del formulario alcance aisladas. En caso afirmativo, he replicado un escenario similar en este violín http://jsfiddle.net/W7YrZ/2/.

Resumen de lo que estaba tratando de hacer.

1) Asigne un atributo umbilical en el ng-repeat con el elemento actual de la iteración.

2) Luego estoy evaluando este atributo dentro de la función de vinculación en el contexto del alcance principal, que da una referencia (puntero) a uno del objeto de matriz en la matriz de alcance principal aquí profiles.

3) Luego, como @Mark Rajcok dice "los primitivos se copian por valor, mientras que los objetos se copian por referencia". Estoy vinculando ese objeto que pasó por el paso 2 a los cuadros de texto en la cadena de la plantilla.

+0

Esto funcionó de maravilla para mí, y era la clave que me faltaba (en mi caso estaba escribiendo una directiva de intervalo de fechas y me costaba conseguir que el ng-model se asignara a una variable de rango inicial y final). – jadrake

-3

por razones de limpieza de código jQuery en angular y para la validación de JavaScript, cambiando el selector $ en angular.element

$('<input>').addClass('span3') 

deben escribirse

angular.element('<input>').addClass('span3') 
Cuestiones relacionadas