javascript - span - property binding angularjs
AngularJS-ng-model falla en contenteditable<span> (5)
Agregando el comportamiento ng-model-options="{ getterSetter: true }"
a un elemento que tiene ng-model
adjunto. También puede agregar ng-model-options="{ getterSetter: true }"
a un <form>
, lo que habilitará este comportamiento para todas las <input>s
dentro de él.
El ejemplo muestra cómo usar ngModel
con un getter/setter
: página de demostración
Estoy aprendiendo AngularJS. Me he encontrado con algo que no puedo explicar, ni puedo encontrar ninguna explicación para (o solución).
Tengo una aplicación AngularJS simple y estoy intentando enlazar un <span contenteditable="true">
a un valor, pero no funciona. P.EJ:
<!-- Works as expected -->
<input data-ng-model="chunk.value"></input>
<!-- Shows value, but doesn''t bind - changes not reflected in model -->
<span contenteditable="true">{{chunk.value}}</span>
<!-- This is empty -->
<span contenteditable="true" data-ng-model="chunk.value"></span>
¿Cómo puedo hacer que el último tramo use enlaces de 2 vías, de modo que editar su valor actualice chunk.value y viceversa?
El ngModel
no funcionará como señaló @VtoCorleone. ngModel docs
The ngModel directive binds an input,select, textarea (or custom form control) to a property on the scope using NgModelController, which is created and exposed by this directive.
Puede echar un vistazo a la directiva contenteditable .
De lo contrario, la solución potencial: tiene una función que se llama. Esa función luego actualiza el $scope.chunk.value
dentro de su controlador. Y se ocuparía de los contenidos de los otros elementos a medida que se actualice el enlace.
No estoy seguro del aspecto o la funcionalidad exacta que está buscando, pero simplemente póngalo dentro de un <textarea>
y <textarea>
para que se vea como un <span>
(sin borde ni fondo, etc.). Luego, cuando está focus
, agrega un estilo adicional para saber que se puede editar. De esta manera le permitiría usar el ng-model
ya que está destinado a ser utilizado. Aquí hay una implementación básica de este enfoque: Plunker
Para hacer que ng-model
funcione con elementos contenteditable <span>
, use una directiva personalizada:
app.directive(''contenteditable'', [''$sce'', function($sce) {
return {
restrict: ''A'', // only activate on element attribute
require: ''?ngModel'', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
// Specify how UI should be updated
ngModel.$render = function() {
element.html($sce.getTrustedHtml(ngModel.$viewValue || ''''));
};
// Listen for change events to enable binding
element.on(''blur keyup change'', function() {
scope.$evalAsync(read);
});
read(); // initialize
// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if (attrs.stripBr && html === ''<br>'') {
html = '''';
}
ngModel.$setViewValue(html);
}
}
};
}]);
Uso:
<span contenteditable ng-model="userContent">Change me!</span>
<p>{{userContent}}</p>
Para más información, ver
- Referencia de la API de
ngModelController
AngularJS - Ejemplo de control personalizado - Referencia para desarrolladores de AngularJS - Crear directivas personalizadas
La DEMO
angular.module(''customControl'', [''ngSanitize''])
.directive(''contenteditable'', [''$sce'', function($sce) {
return {
restrict: ''A'', // only activate on element attribute
require: ''?ngModel'', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
// Specify how UI should be updated
ngModel.$render = function() {
element.html($sce.getTrustedHtml(ngModel.$viewValue || ''''));
};
// Listen for change events to enable binding
element.on(''blur keyup change'', function() {
scope.$evalAsync(read);
});
read(); // initialize
// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if (attrs.stripBr && html === ''<br>'') {
html = '''';
}
ngModel.$setViewValue(html);
}
}
};
}]);
[contenteditable] {
border: 1px solid black;
background-color: white;
min-height: 20px;
}
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angular-sanitize/angular-sanitize.js"></script>
<body ng-app="customControl">
<span contenteditable ng-model="userContent">Change me!</span>
<hr>
Content={{userContent}}
</body>
ng-model
no está diseñado para usarse con span
. Si es absolutamente necesario, puede escribir una directiva personalizada para esto. Esta directiva configurará un keydown,keyup
listener en el span
contentEditable
y actualizará el modelo de alcance (dentro de $apply()
). Esto vinculará el contenido de span al modelo.
Rápidamente creé un plunker para ti. Echale un vistazo. Sincroniza el contenido de <span>
con el modelo de alcance. Abra la consola del navegador para ver la actualización del modelo de alcance cada vez que escriba algo.
ng-bind ! Utilice ng-bind para el enlace unidireccional en ''span''.
Consulte aquí para ver un ejemplo: https://docs.angularjs.org/api/ng/directive/ngBind
Entonces, tu línea sería: <span contenteditable="true" ng-bind="chunk.value"></span>
Espero que esto ayude