Angular.js: ng-model no establece el valor inicial y la posición de la entrada [tipo = rango]

Creado en 18 mar. 2014  ·  35Comentarios  ·  Fuente: angular/angular.js

Básicamente, una entrada de rango se configura con un valor inicial usando ng-model. El valor real del elemento HTML y la posición del control deslizante de rango son incorrectos. Esperaría que la posición del control deslizante y el valor de entrada html estén sincronizados con la variable del modelo.

Aquí hay una reproducción: http://jsfiddle.net/fschwiet/HVp2J/

Verificado en Chrome y Firefox ejecutándose en Windows 8.

Veo que hay otros problemas abiertos para la entrada [tipo = rango], no está claro que estén relacionados.

forms moderate duplicate broken expected use bug

Comentario más útil

Con la nueva función de Reacciones de GitHub, ya no necesitas comentar "+1". En su lugar, puede marcar su interés haciendo clic en "+: smile:" en la parte superior derecha del primer comentario en este número, luego eligiendo: +1: ("+1"). Esto evita enviar una notificación inútil a todas las personas suscritas a este problema.

Todos 35 comentarios

Esto sigue siendo un problema con Angular 1.2.14: http://jsfiddle.net/HVp2J/7/

Como solución alternativa, se puede establecer el valor del modelo dentro de un controlador $ timeout.

$ timeout no ayuda, el problema persiste.

@fschwiet : http://jsfiddle.net/HVp2J/9/

@ Rajat-Chowdhary Lo siento, debería haber incluido un ejemplo de código que muestre cómo puede funcionar $ timeout como solución alternativa :

La solución alternativa se siente arriesgada ya que el valor del modelo no se puede inicializar hasta la devolución de llamada $ timeout para que la solución funcione.

Parece que encontré el problema.
Angular establece el valor antes de establecer el mínimo, el máximo y el paso, por lo que parece que el rango está en la posición incorrecta. Para resolver el problema utilicé esta directiva.

angular.module('angular-range', []).directive('range', function() {
    return {
        replace: true,
        restrict: 'E',
        scope: {
            value: '=ngModel',
            min: '=rangeMin',
            max: '=rangeMax',
            step: '=rangeStep',
        },
        template: '<input type="range"/>',
        link: function(scope, iElement, iAttrs) {
            scope.$watch('min', function() { setValue(); });
            scope.$watch('max', function() { setValue(); });
            scope.$watch('step', function() { setValue(); });
            scope.$watch('value', function() { setValue(); });

            function setValue() {
                if (
                    angular.isDefined(scope.min) &&
                    angular.isDefined(scope.max) &&
                    angular.isDefined(scope.step) &&
                    angular.isDefined(scope.value)
                ) {
                    iElement.attr("min", scope.min);
                    iElement.attr("max", scope.max);
                    iElement.attr("step", scope.step);
                    iElement.val(scope.value); 
                }
            }
            function read() {
                scope.value = iElement.val();
            }

            iElement.on('change', function() {
                scope.$apply(read);
            });
        }
    };
});

Aquí está la nueva versión de ngRange sin alcance privado:

.module('ngRange', [])
.directive('ngRange', function() {
    return {
        replace: true,
        restrict: 'E',
        require: 'ngModel',
        template: '<input type="range"></input>',
        link: function(scope, element, attrs, ngModel) {
            var ngRangeMin;
            var ngRangeMax;
            var ngRangeStep;
            var value;

            if (!angular.isDefined(attrs.ngRangeMin)) {
                ngRangeMin = 0;
            } else {
                scope.$watch(attrs.ngRangeMin, function(newValue, oldValue, scope) {
                    if (angular.isDefined(newValue)) {
                        ngRangeMin = newValue;
                        setValue();
                    }
                });
            }
            if (!angular.isDefined(attrs.ngRangeMax)) {
                ngRangeMax = 100;
            } else {
                scope.$watch(attrs.ngRangeMax, function(newValue, oldValue, scope) {
                    if (angular.isDefined(newValue)) {
                        ngRangeMax = newValue;
                        setValue();
                    }
                });
            }
            if (!angular.isDefined(attrs.ngRangeStep)) {
                ngRangeStep = 1;
            } else {
                scope.$watch(attrs.ngRangeStep, function(newValue, oldValue, scope) {
                    if (angular.isDefined(newValue)) {
                        ngRangeStep = newValue;
                        setValue();
                    }
                });
            }
            if (!angular.isDefined(ngModel)) {
                value = 50;
            } else {
                scope.$watch(
                    function () {
                        return ngModel.$modelValue;
                    }, 
                    function(newValue, oldValue, scope) {
                        if (angular.isDefined(newValue)) {
                            value = newValue;
                            setValue();
                        }
                    }
                );
            }

            function setValue() {
                if (
                    angular.isDefined(ngRangeMin) &&
                    angular.isDefined(ngRangeMax) &&
                    angular.isDefined(ngRangeStep) &&
                    angular.isDefined(value)
                ) {
                    element.attr("min", ngRangeMin);
                    element.attr("max", ngRangeMax);
                    element.attr("step", ngRangeStep);
                    element.val(value); 
                }
            }

            function read() {
                if (angular.isDefined(ngModel)) {
                    ngModel.$setViewValue(value);
                }
            }

            element.on('change', function() {
                if (angular.isDefined(value) && (value != element.val())) {
                    value = element.val();
                    scope.$apply(read);
                }
            });
        }
    };
});

esto sigue siendo un problema, ¿verdad?

http://plnkr.co/edit/MAT5KPkXyWblAJ71L8nK?p=preview

Sí +1

Sí, sigue siendo un problema.

Pregunté algo similar en stackoverflow Cómo inicializar el valor de una entrada [rango] usando AngularJS cuando el valor es superior a 100 . Usando 1.4.0-beta.build.3791, este error todavía está presente.

+1

+1, y empeoró cuando el rango de entrada se combina con un número de entrada.

+1 para este problema

Frente al mismo problema: +1

sí, el mismo problema +1

esto es html5 básico: ¿cuál es el estado de esto? ¿Alguien está trabajando en esto?

teniendo en cuenta esto: https://github.com/danielcrisp/angular-rangeslider/issues/51
donde se lanza Error:
Ajusté la solución

angular.module('common').directive('rangeSlider', [function () {
    return {
        replace: true,
        restrict: 'E',
        require: 'ngModel',
        template: '<input type="range"/>',
        link: function (scope, element, attrs, ngModel) {
            var ngRangeMin;
            var ngRangeMax;
            var ngRangeStep;
            var value;

            function init() {
                if (!angular.isDefined(attrs.ngRangeMin)) {
                    ngRangeMin = 0;
                } else {
                    scope.$watch(attrs.ngRangeMin, function (newValue, oldValue, scope) {
                        if (angular.isDefined(newValue)) {
                            ngRangeMin = newValue;
                            setValue();
                        }
                    });
                }
                if (!angular.isDefined(attrs.ngRangeMax)) {
                    ngRangeMax = 100;
                } else {
                    scope.$watch(attrs.ngRangeMax, function (newValue, oldValue, scope) {
                        if (angular.isDefined(newValue)) {
                            ngRangeMax = newValue;
                            setValue();
                        }
                    });
                }
                if (!angular.isDefined(attrs.ngRangeStep)) {
                    ngRangeStep = 1;
                } else {
                    scope.$watch(attrs.ngRangeStep, function (newValue, oldValue, scope) {
                        if (angular.isDefined(newValue)) {
                            ngRangeStep = newValue;
                            setValue();
                        }
                    });
                }
                if (!angular.isDefined(ngModel)) {
                    value = 50;
                } else {
                    scope.$watch(
                        function () {
                            return ngModel.$modelValue;
                        },
                        function (newValue, oldValue, scope) {
                            if (angular.isDefined(newValue)) {
                                value = newValue;
                                setValue();
                            }
                        }
                    );
                }

                if (!ngModel) {
                    return;
                }
                ngModel.$parsers.push(function (value) {
                    var val = Number(value);
                    if (val !== val) {
                        val = undefined;
                    }
                    return val;
                });
            }

            function setValue() {
                if (
                    angular.isDefined(ngRangeMin) &&
                    angular.isDefined(ngRangeMax) &&
                    angular.isDefined(ngRangeStep) &&
                    angular.isDefined(value)
                    ) {
                    element.attr("min", ngRangeMin);
                    element.attr("max", ngRangeMax);
                    element.attr("step", ngRangeStep);
                    element.val(value);
                }
            }

            function read() {
                if (angular.isDefined(ngModel)) {
                    ngModel.$setViewValue(value);
                }
            }

            element.on('change', function () {
                if (angular.isDefined(value) && (value != element.val())) {
                    value = element.val();
                    scope.$apply(read);
                }
            });

            init();
        }
    };
}
]);

+1, tengo el mismo problema al cambiar [tipo de entrada = rango] con ng-if

También me encontré con este problema y escribí una pregunta de Stack Overflow al respecto, “En Angular, enlazar atributo de la variable de alcance _before_ ngModel enlaza el value . La pregunta incluye un fragmento de código ejecutable que reproduce este problema.

Algunas soluciones se han publicado como respuestas en Stack Overflow. El que se aplica a mi caso implica el uso de manipulación DOM con $inputElement.prop() para establecer los valores de min , max y step (los atributos que se necesiten). Al hacer esta manipulación DOM antes de mi directiva personalizada que está subyacente a <input> 's value es el primer set, evitar el problema.

Mi forma perezosa de abordar este error fue dividir los valores mínimo / máximo y de paso por 100. Entonces, 300 se convierte en 3.0, etc. y los valores caen por debajo de 100. Luego multiplico las cosas según sea necesario. Quizás sea útil para alguien.

+1 Esto es muy molesto.

+1

+1

+1

Otro truco de solución perezosa:

      $timeout(function () {
        angular.element('.slider-input').val(amount);
      });

+1

Con la nueva función de Reacciones de GitHub, ya no necesitas comentar "+1". En su lugar, puede marcar su interés haciendo clic en "+: smile:" en la parte superior derecha del primer comentario en este número, luego eligiendo: +1: ("+1"). Esto evita enviar una notificación inútil a todas las personas suscritas a este problema.

Resolví mi problema usando el método ondrag eliminando ng-model.
revisa esto http://codepen.io/nagarajumusini/pen/BKpGJz

+1

+1

Agregar ng-init a la entrada me funciona para establecer el valor inicial

<input type="range" class="slider-years" min="0" max="30" step="1" value="0" data-ng-model="metier.anneeExperience" data-ng-init="metier.anneeExperience ? metier.anneeExperience = metier.anneeExperience : metier.anneeExperience = 0" />

Solución encontrada en:

http://jsfiddle.net/jestho/8dymV/7/

Estamos trabajando en esto (finalmente). Cerrando como un duplicado de https://github.com/angular/angular.js/issues/5892

$ (documento) .ready (function () {
angular.element ('. yourclasshere'). val (valueoftheslideronload);
});

esta solución de jQuery funciona para que pueda establecer un valor cuando se carga la página, pero sea cual sea el valor de los controles deslizantes, no se sincronizará hasta que se toque.

@davedx Quizás esta sea la mejor manera antes de que se resuelva el problema.

<input type="range" min="15" data-ng-init="signup.age=30" value="30" max="85" step="1" name="ageInput" class="form-control input-lg" ng-model="signup.age" oninput="ageOutputId.value = ageInput.value" /> <output name="ageOutputName" id="ageOutputId">30</output>

¿Fue útil esta página
0 / 5 - 0 calificaciones