Angular.js: angular.element.scope () retorna indefinido

Criado em 9 out. 2014  ·  29Comentários  ·  Fonte: angular/angular.js

angular.element.scope () é indefinido quando o aplicativo é carregado no iframe alterando o atributo src do iframe.

O código a seguir deve retornar a referência ao escopo, mas retorna indefinido:

angular.element(document.body).scope()

O código acima é executado no manipulador onclick depois que o documento é carregado e o angular termina o bootstrap:

<script>
    document.addEventListener("click", function(){
        console.log(angular.element(document.body).scope());
    });
</script>

O problema se manifesta apenas quando o documento é carregado no iframe, modificando seu atributo src.
Testado com 1.3.0-rc.5, sem jquery.

jqLite more info

Comentários muito úteis

Se você deseja habilitar as informações de depuração temporariamente (por exemplo, para depurar um problema em um aplicativo de produção ao vivo), você pode usar angular.reloadWithDebugInfo() conforme descrito aqui .

Todos 29 comentários

Você pode fornecer uma reprodução em plnkr do problema, por favor?

Tenho o mesmo problema em meu próprio projeto, mas não consigo reproduzi-lo usando o plnkr.

escopo () retorna indefinido em qualquer elemento.

Usar JQLite ou JQuery 2.1.1 faz o mesmo.

AngularJS 1.3.1.

Experimente isto:

document.addEventListener('DOMContentLoaded', function () {
  angular.element(document.body).scope();
});

você está desabilitando informações de depuração em seu projeto @VictorQueiroz?

@caitp Você o encontrou.

Habilitar as informações de depuração de volta é uma boa solução para esse problema.

uma boa solução alternativa

: smile:: smile:: smile:

Desculpe pessoal por não reagir por um tempo. O problema está de alguma forma relacionado ao jqCache ou, mais especificamente, à maneira como o expandoId é criado. Em RCs mais antigos, o id foi criado assim:
var expandoId = element[JQLite.expando];
Nos mais novos, o id é obtido usando a propriedade codificada:
var expandoId = element.ng339;
Reverter a mudança resolveu o problema.
Infelizmente, não sei muito sobre essas coisas, então, se alguém pudesse esclarecer a funcionalidade, talvez eu pudesse descrever o problema com mais detalhes.

Nossa, obrigado @caitp, isso estava me deixando louco!
Deve haver uma nota no documento em $ compileProvider explicando que $compileProvider.debugInfoEnabled(false) fará com que a função scope() retorne indefinida, se esse for o comportamento esperado.

Edit: que pena, já está no doc

Chame este método para habilitar / desabilitar várias informações de tempo de execução de depuração no compilador, como adicionar informações de ligação e uma referência ao escopo atual em elementos DOM.

Existe uma maneira de contornar isso; tendo debugInfoEnabled (false), mas ainda sendo capaz de acessar o escopo de um elemento?

Se você deseja habilitar as informações de depuração temporariamente (por exemplo, para depurar um problema em um aplicativo de produção ao vivo), você pode usar angular.reloadWithDebugInfo() conforme descrito aqui .

Acho que @gkalpak esclareceu as coisas aqui!

Por que fechar? Encontrar uma solução alternativa não significa que o problema foi corrigido, o scope () deve retornar o escopo anexado, independentemente do modo de depuração.

Se não for possível, deve ser claramente documentado no documento angular.element #scope ().

@Toilal Eu o fechei, pois já está documentado conforme mencionado nos comentários anteriores deste tópico. Mas se você acredita que deve ser documentado em outros lugares também, um RP seria muito apreciado!

Não posso porque não tenho certeza se os métodos de bruxa do angular.element não funcionarão ao desabilitar a depuração. scope () com certeza porque eu tentei, mas e os outros, como controlador (), injetor () ...

Após o teste, ele afeta apenas scope () e isolateScope (). Vou documentar isso e fazer um PR.

Mas existe alguma maneira de recuperar o escopo de um elemento DOM enquanto as informações de depuração estão desabilitadas?

@Toilal - não realmente - as informações de escopo foram removidas por expor que têm impacto no desempenho - é por isso que estão escondidas atrás de um sinalizador de depuração.

Mas não seria tão difícil escrever uma diretiva que pudesse fazer isso e colocá-la nos elementos que você precisa verificar

Obrigado @ pkozlowski-opensource. Eu adicionei uma pequena frase sobre scope () e isolateScope () em docs, porque levo algum tempo para descobrir por que esses métodos não funcionaram em meu aplicativo.

@ocombe Isso é o que farei, porque estou escrevendo um componente de IU e não posso contar com o scope / isolateScope, pois o desenvolvedor final pode desabilitar as informações de depuração (como é recomendado).

setTimeout (function () {
console.log (angular.element (document.body) .scope ());
}, 100);

qq 20160115164505

@ronnievdv

Existe uma maneira de contornar isso; tendo debugInfoEnabled (false), mas ainda sendo capaz de acessar o escopo de um elemento?

Usei o seguinte método snipet _ (não recomendado) _ na função link da definição de diretiva.

link: function(scope, element, attrs) {
  var isolatedScope = scope.$$childTail;
}

Existe alguma maneira de verificar se debugInfo foi desativado ou algum sinalizador para ele?

De dentro do aplicativo, você pode usar $compileProvider.debugInfoEnabled() .
Se você deseja depurar uma instância ativa que tem informações de depuração desabilitadas (por exemplo, uma implantação de produção), você pode chamar angular.reloadWithDebugInfo() do console e ele irá recarregar o aplicativo com as informações de depuração habilitadas.

@gkalpak Eu só quero verificar se as informações de depuração estão habilitadas ou não. Um pouco assim.

if(angular.isDebugInfoEnabled()) {
  // Do something
}

@hemkaran , ainda não é óbvio _onde_ você deseja verificar. Presumo que de dentro do seu aplicativo.
Se for esse o caso, você pode usar $compileProvider.debugInfoEnabled() .

@Toilal Você escreveu uma diretiva como essa? Se sim, você se importaria de compartilhar? Estou tendo esse problema agora. Presumo que encontrarei uma solução, mas ter uma segunda opinião sobre como resolvê-la realmente não faria mal.
cc @ocombe

Desculpe, não uso mais o Angular 1 e nunca tive que escrever tal diretiva (porque eu só precisava dessa informação no modo dev)

Eu fiz o seguinte. Veremos se meus companheiros deixarão passar pela revisão :)

function exposeScope() {
    return {
        restrict: 'A',
        link: function(scope, element) {
            element[0].APPNAME = {
                getScope: function() {
                    return scope;
                }
            };
        }
    };
}

return {
        restrict: 'A',
        scope: false,
        link: function(scope, elem) {
            elem.data('$scope', scope);
        }
    };

Você também pode definir $ isolateScope da mesma forma, se precisar.

Esta página foi útil?
0 / 5 - 0 avaliações