Establecer la variable de alcance angular en el marcado

94

Pregunta simple: ¿Cómo puedo establecer un valor de alcance en html, para que lo lea mi controlador?

var app = angular.module('app', []);

app.controller('MyController', function($scope) {
  console.log($scope.myVar);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app'>
  <div ng-controller="MyController" app-myVar="test">
    {{myVar}}
  </div>
</div>

JSFiddle: http://jsfiddle.net/ncapito/YdQcX/

Nada
fuente
Puede que sea mejor que cree una directiva para manejar esto. Una directiva encapsularía: los parámetros, un controlador específico para esta directiva y una plantilla para el marcado 'myMap'.
Ian Mercer
Eso es realmente lo que hice ... solo tuve algunos problemas para acceder a $ scope.myVar en el controlador de la directiva. ¿Por qué tengo que usar un reloj en el controlador para acceder a las variables de alcance?
Nix
1
¿Quizás podrías publicar tu directiva? Eche un vistazo a "Comprender la transclusión y los alcances" aquí docs.angularjs.org/guide/directive Probablemente necesite un alcance: {myVar: '='} y diría my-var="foo"cuando lo llame. Tenga en cuenta el uso de guión frente a camelCase. Nota: fooaquí se evalúa , si no desea que use '@' en la definición del alcance para acceder al valor del atributo.
Ian Mercer
1
@Nix ¿Puede explicar por qué es necesario inicializar el valor en la vista, en lugar de en su controlador? Supongo que ya sabe que esa no es la forma convencional de inicializar valores (de lo contrario, no estaría preguntando), y otros podrán brindarle mejores respuestas si comprenden mejor su caso de uso.
Sean the Bean
1
@SeantheBean era joven y tonto ...;) no tengo ni idea de por qué necesitaba hacerlo. Probablemente estaba tratando de hackear algo.
Nix

Respuestas:

138

ng-initno funciona cuando asigna variables dentro del ciclo. Utilizar {{myVariable=whatever;""}}

El final ""detiene la evaluación de la expresión angular en cualquier texto.

Luego, simplemente puede llamar {{myVariable}}para generar su valor de variable.

Encontré esto muy útil al iterar múltiples matrices anidadas y quería mantener mi información de iteración actual en una variable en lugar de consultarla varias veces.

Glogo
fuente
1
Aunque esto funciona, parece hacky. Es decir, generalmente es una buena práctica usar {{}}solo para generar una sola variable, no para asignar variables. Yo diría que stackoverflow.com/a/16799763/814160 es más correcto (menos código JS en la vista).
Sean the Bean
1
+1 para @SeantheBean - He probado esto. Parece haber problemas con los controladores secundarios y el alcance de la asignación de la variable en el marcado. La directiva funciona para mis propósitos y parece ser una solución sólida.
Paul Carlton
2
Esto no parece funcionar en angular2 / 4 - Los enlaces no pueden contener asignaciones
Demodave
1
@Demodave, en su lugar, debe establecer todas las variables de su controlador en el código de TypeScript y usar la plantilla solo para conectar Typecript a HTML. La plantilla no debe asignar variables.
boxmein
80

ngInit puede ayudar a inicializar variables.

<div ng-app='app'>
    <div ng-controller="MyController" ng-init="myVar='test'">
        {{myVar}}
    </div>
</div>

ejemplo de jsfiddle

Mark Coleman
fuente
3
Cabe señalar que no recomiendan esta solución para aplicaciones reales (pero realmente no sugieren una alternativa): docs.angularjs.org/guide/dev_guide.mvc.understanding_model
Mike Robinson
Esto funcionó para mí, sin embargo, al principio la variable aún no estaba definida en el controlador. Hice un pequeño ciclo de intervalo: var interval = setInterval (function () {if ($ scope.whatever) {// dostuff clearInterval (interval);}}, 10);
roelleor
19

Cree una directiva llamada myVarcon

scope : { myVar: '@' }

y llámalo así:

<div name="my_map" my-var="Richmond,VA">

Tenga en cuenta en particular la referencia de caso de camello en la directiva al nombre de la etiqueta con guión.

Para obtener más información, consulte "Comprensión de la transclusión y los alcances" aquí: http://docs.angularjs.org/guide/directive

Aquí hay un Fiddle que muestra cómo puede copiar valores de atributos a variables de alcance de varias formas diferentes dentro de una directiva.

Ian Mercer
fuente
Quiero poder hacer varios var-nick='my' var-nick2='test'. A menos que pueda pensar en una forma de implementarlo con directivas que solo voy a usarng-init
Nix
Puede incluir múltiples atributos en el alcance, todo lo que necesita es que uno de ellos sea el nombre de la directiva que desea ejecutar (o incluir ese nombre de directiva también en el html). scope: {varNick: '@', varNick2: '@'}
Ian Mercer
¿Pero no es escalable? ¿Tendría que definir una directiva por variable?
Nix
No, no necesita una directiva por variable. Eche un vistazo al violín que agregué a la respuesta.
Ian Mercer
Lo siento, me perdí la lectura, tu ejemplo es perfecto, mi único cambio fue el alcance {'@': '@ "}.
Nix
10

Puede establecer valores de html como este. No creo que haya una solución directa de angular todavía.

 <div style="visibility: hidden;">{{activeTitle='home'}}</div>
ibsenv
fuente
7
Buen truco ... <div style="display: none">sin embargo lo recomendaría .
Roger
3

Puede usar ng-initcomo se muestra a continuación

<div class="TotalForm">
  <label>B/W Print Total</label>
  <div ng-init="{{BWCount=(oMachineAccounts|sumByKey:'BWCOUNT')}}">{{BWCount}}</div>
</div>
<div class="TotalForm">
  <label>Color Print Total</label>
  <div ng-init="{{ColorCount=(oMachineAccounts|sumByKey:'COLORCOUNT')}}">{{ColorCount}}</div>
</div>

y luego use la variable de alcance local en otras secciones:

<div>Total: BW: {{BWCount}}</div>
<div>Total: COLOR: {{ColorCount}}</div>
Mahesh
fuente
Me gusta este enfoque; parece menos hacky. Sin embargo, una aclaración, ng-init no necesita las llaves.
mklbtz
1
$scope.$watch('myVar', function (newValue, oldValue) {
        if (typeof (newValue) !== 'undefined') {
            $scope.someothervar= newValue;
//or get some data
            getData();
        }


    }, true);

La variable se inicializa después del controlador, por lo que debe vigilarlo y, cuando no esté inicializado, utilizarlo.

Senad Mulaosmanović
fuente
0

Me gusta la respuesta, pero creo que sería mejor que creara una función de alcance global que le permita establecer la variable de alcance necesaria.

Entonces en el globalController crea

$scope.setScopeVariable = function(variable, value){
    $scope[variable] = value;
}

y luego en su archivo html llámelo

{{setScopeVariable('myVar', 'whatever')}}

Esto le permitirá usar $ scope.myVar en su controlador respectivo

Lance N. Solomon
fuente
0

Si no está en un bucle, puede usar ng-init; de lo contrario, puede usar

{{var=foo;""}}

el "" no permite mostrar su var

Yohann JAFFRES
fuente