Eu tenho um controlador responsável pela comunicação com uma API para atualizar as propriedades de um usuário, nome, email, etc. Cada usuário tem um 'id'
que é passado do servidor quando a página de perfil é exibida.
Gostaria de passar esse valor para o controlador AngularJS para que ele saiba qual é o ponto de entrada da API para o usuário atual. Eu tentei passar o valor ng-controller
. Por exemplo:
function UserCtrl(id, $scope, $filter) {
$scope.connection = $resource('api.com/user/' + id)
e no HTML
<body ng-controller="UserCtrl({% id %})">
onde {% id %}
imprime o ID enviado do servidor. mas eu recebo erros.
Qual é a maneira correta de passar um valor para um controlador em sua criação?
javascript
angularjs
nickponline
fonte
fonte
Respostas:
Notas:
Esta resposta é antiga. Esta é apenas uma prova de conceito de como o resultado desejado pode ser alcançado. No entanto, pode não ser a melhor solução, conforme alguns comentários abaixo. Não tenho nenhuma documentação para apoiar ou rejeitar a abordagem a seguir. Consulte alguns dos comentários abaixo para uma discussão mais aprofundada sobre este tópico.
Resposta original:
Eu respondi isso para Sim, você absolutamente pode fazê-lo usando
ng-init
uma simples função init.Aqui está o exemplo disso no plunker
HTML
Javascript
fonte
The only appropriate use of ngInit for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
ng-init
ocorrer - consulte plnkr.co/edit / donCm6FRBSX9oENXh9WJ? p = visualizaçãoEstou muito atrasado para isso e não faço ideia se é uma boa ideia, mas você pode incluir o
$attrs
injetável na função do controlador, permitindo que o controlador seja inicializado usando "argumentos" fornecidos em um elemento, por exemploNovamente, não faço ideia se é uma boa ideia, mas parece funcionar e é outra alternativa.
fonte
ng-init
- se você está tentando se ligam a um valor escopo, ele já está executar a função de controlador antes deng-init
ocorrer - ver plnkr.co/edit/donCm6FRBSX9oENXh9WJ?p=previewIsso também funciona.
Javascript:
Html:
fonte
A visualização não deve ditar a configuração
Em Angular, o modelo nunca deve ditar a configuração, que é inerentemente o que as pessoas desejam quando desejam passar argumentos para os controladores a partir de um arquivo de modelo. Isso se torna uma ladeira escorregadia. Se as definições de configuração estiverem codificadas em modelos (como por um atributo de diretiva ou argumento do controlador), você não poderá mais reutilizá-lo para nada além desse uso único. Em breve, você desejará reutilizar esse modelo, mas com configurações diferentes e agora, para isso, você estará pré-processando os modelos para injetar variáveis antes que elas passem para o angular ou usando diretivas massivas para cuspir gigantes. blocos de HTML para que você reutilize todo o HTML do controlador, exceto a div do wrapper e seus argumentos. Para pequenos projetos, não é grande coisa. Para algo grande (no que a angular se destaca), fica feio rapidamente.
A Alternativa: Módulos
Esse tipo de configuração é o que os módulos foram projetados para manipular. Em muitos tutoriais angulares, as pessoas têm um único módulo para toda a sua aplicação, mas, na verdade, o sistema é projetado e suporta totalmente muitos módulos pequenos, cada um que envolve pequenos pedaços da aplicação total. Idealmente, controladores, módulos etc. seriam declarados em arquivos separados e costurados em pedaços reutilizáveis específicos. Quando seu aplicativo é projetado dessa maneira, você recebe muita reutilização, além dos argumentos fáceis do controlador.
O exemplo abaixo possui 2 módulos, reutilizando o mesmo controlador, mas cada um com suas próprias configurações. As definições de configuração são passadas via injeção de dependência usando
module.value
. Isso segue o caminho angular porque temos o seguinte: injeção de dependência do construtor, código do controlador reutilizável, modelos de controlador reutilizáveis (a div do controlador pode ser facilmente incluída com ng-include), sistema facilmente testável por unidade sem HTML e, por fim, reutilizável módulos como o veículo para costurar as peças.Aqui está um exemplo:
Veja em ação: jsFiddle .
fonte
Como @akonsu e Nigel Findlater sugerir, você pode ler a url onde url é
index.html#/user/:id
com$routeParams.id
e usá-lo dentro do controlador.seu aplicativo:
o serviço de recursos
o controlador
então,
elm
é acessível na visualização, dependendo doid
.fonte
Se
ng-init
não é para passar objetos$scope
, você sempre pode escrever sua própria diretiva. Então aqui está o que eu tenho:http://jsfiddle.net/goliney/89bLj/
Javasript:
Html:
Mas minha abordagem só pode modificar objetos, que já estão definidos no controlador.
fonte
Parece que a melhor solução para você é realmente uma diretiva. Isso permite que você ainda tenha seu controlador, mas defina propriedades personalizadas para ele.
Use isso se precisar acessar variáveis no escopo de disposição:
Use isso se você não precisar acessar variáveis no escopo de disposição:
fonte
Eu encontrei variáveis úteis de $ routeProvider úteis.
Por exemplo, você usa um controlador MyController para várias telas, passando alguma variável muito importante "mySuperConstant" para dentro.
Use essa estrutura simples:
fonte
Você pode fazer isso ao configurar as rotas para, por exemplo,
E depois use-o como
Então, aqui, quando configuramos a rota que enviamos: itemType e recuperamos mais tarde a partir de $ routeParams.
fonte
Existe outra maneira de passar parâmetros para um controlador injetando $ routeParams no seu controlador e, em seguida, usando os parâmetros de URL descritos aqui Qual é a maneira mais concisa de ler os parâmetros de consulta no AngularJS?
fonte
Esta pergunta é antiga, mas lutei por um longo tempo tentando obter uma resposta para esse problema que funcionasse para minhas necessidades e não a encontrasse facilmente. Acredito que minha solução a seguir é muito melhor do que a atualmente aceita, talvez porque o angular tenha adicionado funcionalidade desde que a pergunta foi feita originalmente.
Resposta curta, usando o método Module.value permite passar dados para um construtor de controlador.
Veja meu desentupidor aqui
Crio um objeto de modelo, associo-o ao controlador do módulo, referenciando-o ao nome 'model'
HTML / JS
O construtor no meu controlador aceita um parâmetro com o mesmo identificador 'model' que ele pode acessar.
Controlador
Notas:
Estou usando a inicialização manual do bootstrapping , o que me permite inicializar meu modelo antes de enviá-lo para o angular. Isso funciona muito mais bem com o código existente, pois você pode esperar para configurar seus dados relevantes e compilar apenas o subconjunto angular do seu aplicativo sob demanda quando desejar.
No plunker, adicionei um botão para alertar os valores do objeto de modelo que foram inicialmente definidos em javascript e passados para angular, apenas para confirmar que angular está realmente fazendo referência ao objeto de modelo, em vez de copiá-lo e trabalhar com uma cópia.
Nesta linha:
Estou passando o objeto MyController para a função Module.controller, em vez de declarar como uma função embutida. Eu acho que isso nos permite definir muito mais claramente nosso objeto de controlador, mas a documentação Angular tende a fazê-lo em linha, então achei que precisava de esclarecimentos.
Estou usando a sintaxe "controller as" e atribuindo valores à propriedade "this" do MyController, em vez de usar a variável "$ scope". Acredito que isso funcionaria bem usando $ scope também, a atribuição do controlador seria algo parecido com isto:
e o construtor do controlador teria uma assinatura como esta:
Se, por qualquer motivo que você quiser, também poderá anexar esse modelo como valor de um segundo módulo, que será anexado como uma dependência ao seu módulo principal.
Eu acredito que a solução dele é muito melhor do que a atualmente aceita, porque
A maneira como o Angular parece funcionar na maioria dos outros exemplos que eu já vi tem o controlador definindo os dados do modelo, o que nunca fez sentido para mim, não há separação entre o modelo e o controlador, o que realmente não parece MVC para mim. Esta solução permite que você realmente tenha um objeto de modelo completamente separado que você passa para o controlador. Observe também que, se você usar a diretiva ng-include, poderá colocar todo o seu html angular em um arquivo separado, separando completamente a visualização e o modelo do seu modelo em partes modulares separadas.
fonte
Se estiver usando o angular-ui-router, esta é a solução correta: https://github.com/angular-ui/ui-router/wiki#resolve
Basicamente, você declara um conjunto de dependências para "resolver" antes que o controlador seja instanciado. Você pode declarar dependências para cada um dos seus "estados". Essas dependências são passadas no "construtor" do controlador.
fonte
Uma maneira de fazer isso seria ter um serviço separado que possa ser usado como um 'navio' para os argumentos em que eles são membros de dados públicos.
fonte
Eu realmente não gostei de nenhuma das soluções aqui para o meu caso de uso específico, então imaginei que postaria o que fiz porque não o vi aqui.
Eu simplesmente queria usar um controlador mais como uma diretiva, dentro de um loop ng-repeat:
Agora, para acessar a
objParameter
criação em cada DiretivoLikeController (ou obter o objParameter atualizado a QUALQUER MOMENTO), tudo o que preciso fazer é injetar $ scope e chamar$scope.$eval('objParameter')
:A única desvantagem real que vejo é que requer que o controlador pai saiba que o parâmetro está nomeado
objParameter
.fonte
Não, não é possível. Eu acho que você pode usar o ng-init como hack http://docs.angularjs.org/api/ng.directive:ngInit .
fonte
ng-init
ocorra - consulte plnkr.co/edit / donCm6FRBSX9oENXh9WJ? p = visualizaçãoAqui está uma solução (baseada na sugestão de Marcin Wyszynski) que funciona onde você deseja passar um valor para o seu controlador, mas você não está declarando explicitamente o controlador no seu html (que o ng-init parece exigir) - se, por exemplo, você está renderizando seus modelos com ng-view e declarando cada controlador para a rota correspondente via routeProvider.
JS
html
Nesta solução, o CurrentUser é um serviço que pode ser injetado em qualquer controlador, com a propriedade .name disponível.
Duas notas:
um problema que encontrei é que .name é definido após o carregamento do controlador, portanto, como solução alternativa, tenho um tempo limite curto antes de renderizar o nome de usuário no escopo do controlador. Existe uma maneira elegante de esperar até que .name seja definido no serviço?
essa é uma maneira muito fácil de obter um usuário atual no seu aplicativo Angular com toda a autenticação mantida fora do Angular. Você pode ter um before_filter para impedir que usuários não logados acessem o html em que seu aplicativo Angular é inicializado e, nesse html, você pode interpolar apenas o nome do usuário conectado e até o ID deles, se desejar interagir com os detalhes do usuário. via solicitações http do seu aplicativo Angular. Você pode permitir que usuários não conectados usem o Angular App com um 'usuário convidado' padrão. Qualquer conselho sobre por que essa abordagem seria ruim seria bem-vindo - é fácil demais ser sensato!)
fonte
Esta é uma expansão da excelente resposta de @Michael Tiller . Sua resposta funciona para inicializar variáveis a partir da visualização injetando o
$attrs
objeto no controlador. O problema ocorre se o mesmo controlador for chamado a partir de$routeProvider
quando você navegar pelo roteamento. Então você recebe o erro do injetor,Unknown provider : $attrsProvider
porque$attrs
só está disponível para injeção quando a visualização é compilada. A solução é passar a variável (foo)$routeParams
ao inicializar o controlador a partir da rota e$attrs
ao inicializar o controlador a partir da visualização. Aqui está a minha solução.Da rota
Isso lida com um URL como
'/mypage/bar'
. Como você pode ver, o foo é passado pelo parâmetro url e fornecemos$injector
um objeto em branco para$attrs
que não haja erros do injetor.Da vista
Agora o controlador
fonte