Estou tentando criar uma diretiva que criaria um campo de entrada com o mesmo modelo ng que o elemento que cria a diretiva.
Aqui está o que eu vim até agora:
HTML
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
This scope value <input ng-model="name">
<my-directive ng-model="name"></my-directive>
</body>
</html>
Javascript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Felipe";
});
app.directive('myDirective', function($compile) {
return {
restrict: 'E',
scope: {
ngModel: '='
},
template: '<div class="some"><label for="{{id}}">{{label}}</label>' +
'<input id="{{id}}" ng-model="value"></div>',
replace: true,
require: 'ngModel',
link: function($scope, elem, attr, ctrl) {
$scope.label = attr.ngModel;
$scope.id = attr.ngModel;
console.debug(attr.ngModel);
console.debug($scope.$parent.$eval(attr.ngModel));
var textField = $('input', elem).
attr('ng-model', attr.ngModel).
val($scope.$parent.$eval(attr.ngModel));
$compile(textField)($scope.$parent);
}
};
});
No entanto, não estou confiante de que este é o caminho certo para lidar com esse cenário e há um erro que meu controle não está sendo inicializado com o valor do campo de destino do modelo ng.
Aqui está um plunker do código acima: http://plnkr.co/edit/IvrDbJ
Qual é a maneira correta de lidar com isso?
EDIT : Depois de remover o ng-model="value"
do modelo, isso parece estar funcionando bem. No entanto, manterei essa questão em aberto, porque desejo verificar novamente se esta é a maneira correta de fazer isso.
scope
e configurá-lo parascope: false
? Como vincularng-model
nesse caso?Respostas:
EDIT : Esta resposta é antiga e provavelmente desatualizada. Apenas um aviso, para que não desvie as pessoas. Como não uso mais o Angular, não estou em uma boa posição para fazer melhorias.
Na verdade, é uma lógica muito boa, mas você pode simplificar um pouco as coisas.
Directiva
Html com diretiva
CSS
Você pode vê-lo em ação com este Plunker .
Aqui está o que eu vejo:
Edição Como mencionado por Mark em seu comentário, não há razão para que você não possa usar o ng-model, apenas para manter a convenção.
Em geral, suas diretivas devem usar o escopo isolado (que você fez corretamente) e usar o escopo do tipo '=' se desejar que um valor em sua diretiva seja sempre mapeado para um valor no escopo pai.
fonte
contenteditable
exemplos de diretiva na documentação angular - página de formulários , página NgModelController - usam o ng-model. E a página ngModelController diz que esse controlador "deve ser estendido por outras diretrizes".hg-model
(e não a questão do acoplamento, IMO). Dessa forma, o contexto de dados sempre usa o ng-model, seja uma<input>
diretiva ou uma diretiva personalizada, simplificando a sobrecarga cognitiva para o gravador de HTML. Ou seja, evita que o gravador de HTML precise descobrir qual é o nomemy-directive-var
para cada diretiva, especialmente porque não há preenchimento automático para ajudá-lo.ng-model-options
nenhuma das outras coisas do modelo ng, funciona?Peguei uma combinação de todas as respostas e agora tenho duas maneiras de fazer isso com o atributo ng-model:
Mostrar snippet de código
Não tenho certeza se gosto da compilação no momento do link. No entanto, se você estiver apenas substituindo o elemento por outro, não precisará fazer isso.
Ao todo, prefiro o primeiro. Basta definir o escopo
{ngModel:"="}
e definirng-model="ngModel"
onde você deseja no seu modelo.Atualização : inclinei o trecho de código e o atualizei para o Angular v1.2. Acontece que isolar o escopo ainda é o melhor, especialmente quando não estiver usando o jQuery. Então, tudo se resume a:
Você está substituindo um único elemento: Apenas substitua-o, deixe o escopo em branco, mas observe que a substituição foi descontinuada para a v2.0:
Caso contrário, use isto:
fonte
ng-model
em um escopo isolado?não é tão complicado: no seu diretório, use um apelido:
scope:{alias:'=ngModel'}
no seu html, use normalmente
fonte
Você só precisa do ng-model quando precisa acessar o $ viewValue ou $ modelValue do modelo. Consulte NgModelController . E nesse caso, você usaria
require: '^ngModel'
.Quanto ao resto, veja a resposta de Roys .
fonte
^
deve ser não somente se a NG-modelo é aplicado em um elemento paiEsta é uma resposta um pouco tardia, mas achei este post incrível sobre o
NgModelController
qual acho que é exatamente o que você estava procurando.TL; DR - você pode usar
require: 'ngModel'
e adicionarNgModelController
à sua função de vinculação:Dessa forma, não são necessários hacks - você está usando o recurso incorporado do Angular
ng-model
fonte
Eu não definiria o ngmodel por meio de um atributo, você pode especificá-lo diretamente no modelo:
plunker : http://plnkr.co/edit/9vtmnw?p=preview
fonte
Desde o Angular 1.5, é possível usar componentes. Os componentes são o caminho a percorrer e resolvem esse problema com facilidade.
Dentro do YourController, tudo o que você precisa fazer é:
fonte
input ng-model="$ctrl.ngModel"
e ele será sincronizado com o $ ctrl.result também.Criar um escopo isolado é indesejável. Eu evitaria usar o atributo scope e faria algo assim. scope: true fornece um novo escopo filho, mas não é isolado. Em seguida, use a análise para apontar uma variável de escopo local para o mesmo objeto que o usuário forneceu ao atributo ngModel.
fonte