Eu tenho um modelo angular no DOM. Quando meu controlador obtém novos dados de um serviço, ele atualiza o modelo no escopo $ e renderiza novamente o modelo. Tudo de bom até agora.
O problema é que eu também preciso fazer um trabalho extra depois que o modelo foi renderizado novamente e estiver no DOM (neste caso, um plugin jQuery).
Parece que deve haver um evento para ouvir, como o AfterRender, mas não consigo encontrar nada disso. Talvez uma diretiva fosse um caminho a percorrer, mas parecia disparar muito cedo também.
Aqui está um jsFiddle descrevendo meu problema: Fiddle-AngularIssue
== ATUALIZAÇÃO ==
Com base em comentários úteis, mudei para uma diretiva para lidar com a manipulação do DOM e implementei um modelo $ watch dentro da diretiva. No entanto, ainda estou tendo o mesmo problema básico; o código dentro do evento $ watch é acionado antes que o modelo seja compilado e inserido no DOM; portanto, o plugin jquery está sempre avaliando uma tabela vazia.
Curiosamente, se eu remover a chamada assíncrona, tudo funcionará bem, então esse é um passo na direção certa.
Aqui está o meu Fiddle atualizado para refletir essas alterações: http://jsfiddle.net/uNREn/12/
fonte
Respostas:
Esta postagem é antiga, mas altero seu código para:
veja jsfiddle .
Espero que ajude você
fonte
Primeiro, o lugar certo para mexer na renderização são as diretivas. Meu conselho seria envolver o DOM manipulando plugins jQuery por diretivas como esta.
Eu tive o mesmo problema e criei esse trecho. Ele usa
$watch
e$evalAsync
para garantir que seu código seja executado depois que diretivas comong-repeat
foram resolvidas e modelos como{{ value }}
renderizados.Espero que isso possa ajudá-lo a evitar alguma luta.
fonte
link
função com atemplateUrl
.Seguindo o conselho de Misko, se você deseja uma operação assíncrona, em vez de $ timeout () (que não funciona)
use $ evalAsync () (que funciona)
Violino . Também adicionei um link "remover linha de dados" que modificará $ scope.assignments, simulando uma alteração nos dados / modelo - para mostrar que a alteração dos dados funciona.
A seção Tempo de execução da página Visão geral conceitual explica que evalAsync deve ser usado quando você precisar que algo ocorra fora do quadro de pilha atual, mas antes que o navegador seja processado. (Acho que aqui ... "o quadro atual da pilha" provavelmente inclui atualizações angulares do DOM.) Use $ timeout se precisar que algo ocorra após a renderização do navegador.
No entanto, como você já descobriu, acho que não há necessidade de operação assíncrona aqui.
fonte
$scope.$evalAsync($scope.assignmentsLoaded(data));
não faz nenhum sentido IMO. O argumento para$evalAsync()
deve ser uma função. No seu exemplo, você está chamando a função no momento em que uma função deve ser registrada para execução posterior.Eu descobri que a solução mais simples (barata e alegre) é simplesmente adicionar um espaço vazio com ng-show = "someFunctionThatAlwaysReturnsZeroOrNothing ()" ao final do último elemento renderizado. Esta função será executada quando verificar se o elemento span deve ser exibido. Execute qualquer outro código nesta função.
Sei que essa não é a maneira mais elegante de fazer as coisas, no entanto, funciona para mim ...
Eu tive uma situação semelhante, embora levemente invertida, onde eu precisava remover um indicador de carregamento quando uma animação começou, em dispositivos móveis, o angular estava inicializando muito mais rápido que a animação a ser exibida, e o uso de uma capa de ng era insuficiente, pois o indicador de carregamento era removido bem antes da exibição de dados reais. Nesse caso, acabei de adicionar a função my return 0 ao primeiro elemento renderizado e, nessa função, inverti o var que oculta o indicador de carregamento. (é claro que adicionei um ng-hide ao indicador de carregamento acionado por esta função.
fonte
$anchorScroll
serviço interno fosse chamado após o DOM renderizado e nada parecia fazer o truque, exceto isso. Hackish, mas funciona.Eu acho que você está procurando $ evalAsync http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync
fonte
Finalmente encontrei a solução, estava usando um serviço REST para atualizar minha coleção. Para converter o jquery da tabela de dados é o seguinte código:
fonte
Eu tive que fazer isso com bastante frequência. Eu tenho uma diretiva e preciso fazer algumas coisas de jquery depois que as coisas do modelo são totalmente carregadas no DOM. então eu coloquei minha lógica no link: function da diretiva e envolvo o código em um setTimeout (function () {.....}, 1); o setTimout será acionado após o carregamento do DOM e 1 milissegundo é o menor período de tempo após o carregamento do DOM antes da execução do código. isso parece funcionar para mim, mas desejo que o angular tenha gerado um evento assim que o modelo for carregado, para que as diretivas usadas por esse modelo possam fazer coisas de jquery e acessar elementos DOM. espero que isto ajude.
fonte
Você também pode criar uma diretiva que execute seu código na função de link.
Veja a resposta do stackoverflow .
fonte
Nem $ scope. $ EvalAsync () ou $ timeout (fn, 0) funcionaram de maneira confiável para mim.
Eu tive que combinar os dois. Fiz uma diretiva e também coloquei uma prioridade maior que o valor padrão para uma boa medida. Aqui está uma diretiva para isso (note que eu uso o ngInject para injetar dependências):
Para chamar a diretiva, você faria o seguinte:
Se você quiser chamá-lo após a execução de ng-repeat, adicionei um espaço vazio em ng-repeat e ng-if = "$ last":
fonte
Em alguns cenários em que você atualiza um serviço e redireciona para uma nova exibição (página) e, em seguida, sua diretiva é carregada antes da atualização dos serviços, você pode usar $ rootScope. $ Broadcast se seu $ watch ou $ timeout falhar
Visão
Controlador
Directiva
fonte
Eu vim com uma solução bastante simples. Não tenho certeza se é a maneira correta de fazê-lo, mas funciona no sentido prático. Vamos assistir diretamente o que queremos que seja renderizado. Por exemplo, em uma diretiva que inclui alguns
ng-repeat
s, eu observaria o comprimento do texto (você pode ter outras coisas!) Dos parágrafos ou o html inteiro. A diretiva será assim:Observe que o código realmente é executado após a renderização ser alterada . Mas acho que, na maioria dos casos, você pode lidar com as situações sempre que houver alterações na renderização. Além disso, você pode comparar esse
p
comprimento (ou qualquer outra medida) com o seu modelo se desejar executar seu código apenas uma vez após a conclusão da renderização. Agradeço quaisquer pensamentos / comentários sobre isso.fonte
Você pode usar o módulo 'jQuery Passthrough' dos utilitários angular-ui . Vinculei com êxito um plug-in do carrossel jQuery touch a algumas imagens que recupero assíncronas de um serviço da web e as renderizo com ng-repeat.
fonte