Definir a variável de escopo angular na marcação

94

Pergunta simples: como posso definir um valor de escopo em html, para ser lido pelo meu 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/

Nix
fonte
Talvez seja melhor criar uma diretiva para lidar com isso. Uma diretiva encapsularia: o (s) parâmetro (s), um controlador específico para esta diretiva e um modelo para a marcação 'myMap'.
Ian Mercer
Isso é realmente o que eu fiz ... apenas tendo alguns problemas ao acessar $ scope.myVar no controlador de diretiva. Por que tenho que usar um relógio no controlador para acessar as variáveis ​​de escopo?
Nix
1
Talvez você possa postar sua diretiva? Dê uma olhada em "Noções básicas sobre transclusão e escopos" aqui docs.angularjs.org/guide/directive Você provavelmente precisa de escopo: {myVar: '='} e você diria my-var="foo"quando o chamasse. Observe o uso de hífen em vez de camelCase. Nota: fooaqui é avaliado , se você não quiser que use '@' na definição do escopo para acessar o valor do atributo.
Ian Mercer
1
@Nix Você pode explicar por que o valor precisa ser inicializado na visualização, em vez de em seu controlador? Presumo que você já saiba que essa não é a maneira convencional de inicializar valores (caso contrário, você não estaria perguntando), e outras pessoas poderão lhe dar respostas melhores se entenderem melhor seu caso de uso.
Sean the Bean
1
@SeantheBean eu era jovem e tolo ...;) não tenho ideia de por que precisava fazer isso. Provavelmente estava tentando hackear algo.
Nix

Respostas:

138

ng-initnão funciona quando você está atribuindo variáveis ​​dentro do loop. Usar {{myVariable=whatever;""}}

O final ""para que a expressão Angular seja avaliada para qualquer texto.

Então, você pode simplesmente chamar {{myVariable}}para gerar o valor da sua variável.

Achei isso muito útil ao iterar várias matrizes aninhadas e queria manter minhas informações de iteração atuais em uma variável em vez de consultá-la várias vezes.

Glogo
fonte
1
Embora funcione, parece hacky. Ou seja, geralmente é uma boa prática usar {{}}apenas para gerar uma única variável, não para atribuir variáveis. Eu diria que stackoverflow.com/a/16799763/814160 é mais correto (menos código JS na visualização).
Sean the Bean
1
+1 para @SeantheBean - eu testei isso. Parece haver problemas com controladores filhos e o escopo da atribuição da variável na marcação. A diretiva funciona para os meus objetivos e parece ser uma solução sólida.
Paul Carlton
2
Isso não parece funcionar no angular2 / 4 - Bindings não podem conter atribuições
Demodave
1
@Demodave você deve, em vez disso, definir todas as suas variáveis ​​de controlador no código Typescript e usar o modelo apenas para conectar Typescript ao HTML. O modelo não deve atribuir variáveis.
boxmein
80

ngInit pode ajudar a inicializar variáveis.

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

exemplo jsfiddle

Mark Coleman
fonte
3
Deve-se observar que eles não recomendam esta solução para aplicativos reais (mas não sugerem uma alternativa): docs.angularjs.org/guide/dev_guide.mvc.understanding_model
Mike Robinson
Isso funcionou para mim, no entanto, no início a variável ainda estava indefinida no controlador. Fiz um pequeno loop de intervalo: var interval = setInterval (function () {if ($ scope.whatever) {// dostuff clearInterval (interval);}}, 10);
roelleor
19

Crie uma diretiva chamada myVarcom

scope : { myVar: '@' }

e chamá-lo assim:

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

Observe em particular a referência do caso camel na diretiva ao nome da marca hifenizada.

Para obter mais informações, consulte "Noções básicas sobre transclusão e escopos" aqui: - http://docs.angularjs.org/guide/directive

Aqui está um Fiddle que mostra como você pode copiar valores de atributos para variáveis ​​de escopo de várias maneiras diferentes dentro de uma diretiva.

Ian Mercer
fonte
Eu quero ser capaz de fazer vários var-nick='my' var-nick2='test'. A menos que você possa pensar em uma maneira de implementá-lo com as diretivas que vou usarng-init
Nix
Você pode incluir vários atributos no escopo, tudo o que você precisa é que um deles seja o nome da diretiva que deseja executar (ou inclua o nome da diretiva também no html). scope: {varNick: '@', varNick2: '@'}
Ian Mercer
Mas não é escalável? Eu teria que definir uma diretiva por variável?
Nix
Não, você não precisa de uma diretiva por variável. Dê uma olhada no violino que adicionei à resposta.
Ian Mercer
Desculpe, não li, seu exemplo é perfeito, minha única alteração foi o escopo {'@': '@ "}.
Nix
10

Você pode definir valores de html assim. Não acho que haja uma solução direta do angular ainda.

 <div style="visibility: hidden;">{{activeTitle='home'}}</div>
ibsenv
fonte
7
Hack agradável ... recomendaria <div style="display: none">no entanto.
Roger
3

Você pode usar ng-initcomo mostrado abaixo

<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>

e usar a variável de escopo local em outras seções:

<div>Total: BW: {{BWCount}}</div>
<div>Total: COLOR: {{ColorCount}}</div>
Mahesh
fonte
Eu gosto dessa abordagem; parece menos hacky. Um esclarecimento, porém, ng-init não precisa das chaves.
mklbtz
1
$scope.$watch('myVar', function (newValue, oldValue) {
        if (typeof (newValue) !== 'undefined') {
            $scope.someothervar= newValue;
//or get some data
            getData();
        }


    }, true);

A variável é inicializada após o controlador, então você precisa vigiá-la e quando ela não inicializar, use-a.

Senad Mulaosmanović
fonte
0

Gostei da resposta, mas acho que seria melhor que você criasse uma função de escopo global que lhe permitiria definir a variável de escopo necessária.

Portanto, no globalController, crie

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

e então em seu arquivo html chame-o

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

Isso permitirá que você use $ scope.myVar em seu respectivo controlador

Lance N. Solomon
fonte
0

Se você não estiver em um loop, você pode usar ng-init, senão você pode usar

{{var=foo;""}}

o "" não permite exibir seu var

Yohann JAFFRES
fonte