Você quer solicitar um recurso ou relatar um bug ?
Não sei se é desejado ou se é um bug
Qual é o comportamento atual?
A primeira $onChanges
chamada é feita antes de $onInit
one.
Com a configuração padrão do angular 1.6 (preassign = false), é possível inicializar os estados do controlador na função $onInit
, visto que as ligações ainda não estão acessíveis no construtor.
Qual é o comportamento esperado?
Acho que seria mais lógico chamar $onInit
primeiro.
O Angular não deve fazer nada enquanto o controlador não estiver totalmente inicializado.
Qual é a motivação / caso de uso para mudar o comportamento?
Se usarmos objetos que devem ser criados na função $onInit
na função $onChanges
; teremos um erro na primeira chamada, pois o controlador ainda não foi inicializado.
Uma solução poderia ser inicializar esses objetos dentro do construtor, mas vamos inicializar o controlador em dois lugares diferentes ...
Quais versões do Angular e quais navegador / sistema operacional são afetados por esse problema? Teste também com as versões mais recentes estáveis e instantâneas (https://code.angularjs.org/snapshot/).
versão angular 1.6
Isso é pretendido (principalmente para corresponder ao comportamento do Angular 2+). Caso você tenha perdido, você pode verificar se é a primeira chamada (pré- $ onInit) de $onChanges
, verificando o valor de retorno do método isFirstChange()
de qualquer um dos SimpleChange
objetos:
{
...
bindings: {foo: '<'},
controller: function SomeController() {
this.$onChanges = function(changes) {
if (changes.foo.isFirstChange()) {
// `$onInit()` has not been called yet...
}
};
}
}
Admito que minha primeira reação foi a mesma. Do ponto de vista do modelo mental, é mais fácil pensar que $onInit()
é a primeira coisa que acontece no controlador; depois $onChanges()
, $onChanges()
, $onChanges()
e finalmente $onDestroy()
.
Mas se você pensar sobre isso, as ligações precisam ser avaliadas e atribuídas à instância do controlador antes de chamar $onInit
. E ao fazer isso, uma alteração nos valores (anteriormente indefinidos) é detectada, que por sua vez precisa ser relatada por meio de $onChanges
.
Fechando, já que está funcionando conforme o esperado (ou pelo menos como pretendido: wink :).
Muito obrigado pela sua resposta, está mais claro agora :)
Eu entendo que isso é intencional, que tal registrarmos a definição da função $ onChanges () dentro de $ onInit ().
@bharatpatil , deve funcionar em AngularJS (1.x.), mas não em Angular (2+).
if (changes.foo.isFirstChange ()) {
//$onInit()
ainda não foi chamado ...
}
@gkalpak Acho que esse argumento está errado. binding.isFirstChange()
método controller.$onInit
deve ser chamado antes do método controller.$onChanges
. Estou errado?
Uma associação sempre tem um valor no início (pode ser undefined
), que é sempre diferente de seu valor pré-inicializado. Assim, $onChanges()
sempre será chamado com changes.foo
antes de chamar $onInit()
.
Não faz sentido lógico que uma associação possa ter um valor antes de ser inicializada. Essa é a definição do dicionário para a palavra inicializar (definir valores iniciais). Você não pode mudar algo se não tiver um valor inicial. Acho que o nome está errado aqui e não é natural.
Não me lembro de uma situação em que não fui forçado a escrever algo como este código:
$onChanges(changesObj: { [index: string]: angular.IChangesObject; }) {
if (!this.isInitialized) return;
...
}
Chamar "alterações" antes da "inicialização" não faz sentido.
Par para o curso com Angular ... por que alguém esperaria que o init acontecesse antes das mudanças?
Comentários muito úteis
Isso é pretendido (principalmente para corresponder ao comportamento do Angular 2+). Caso você tenha perdido, você pode verificar se é a primeira chamada (pré- $ onInit) de
$onChanges
, verificando o valor de retorno do métodoisFirstChange()
de qualquer um dosSimpleChange
objetos:#
Admito que minha primeira reação foi a mesma. Do ponto de vista do modelo mental, é mais fácil pensar que
$onInit()
é a primeira coisa que acontece no controlador; depois$onChanges()
,$onChanges()
,$onChanges()
e finalmente$onDestroy()
.Mas se você pensar sobre isso, as ligações precisam ser avaliadas e atribuídas à instância do controlador antes de chamar
$onInit
. E ao fazer isso, uma alteração nos valores (anteriormente indefinidos) é detectada, que por sua vez precisa ser relatada por meio de$onChanges
.Fechando, já que está funcionando conforme o esperado (ou pelo menos como pretendido: wink :).