Angular.js: Das ng-Modell legt den Anfangswert und die Position der Eingabe nicht fest [Typ = Bereich]

Erstellt am 18. März 2014  ·  35Kommentare  ·  Quelle: angular/angular.js

Grundsätzlich wird mit dem ng-Modell eine Bereichseingabe mit einem Anfangswert eingerichtet. Der tatsächliche Wert des HTML-Elements und die Position des Bereichsschiebereglers sind falsch. Ich würde erwarten, dass die Position des Schiebereglers und der HTML-Eingabewert mit der Modellvariablen synchron sind.

Hier ist ein Repro: http://jsfiddle.net/fschwiet/HVp2J/

Verifiziert auf Chrome und Firefox unter Windows 8.

Ich sehe, dass andere Probleme für die Eingabe geöffnet sind [Typ = Bereich], es ist nicht klar, ob sie zusammenhängen.

forms moderate duplicate broken expected use bug

Hilfreichster Kommentar

Mit der neuen Reaktionsfunktion von GitHub müssen Sie "+1" nicht mehr kommentieren. Stattdessen können Sie Ihr Interesse markieren, indem Sie oben rechts im ersten Kommentar dieser Ausgabe auf „+: smile:“ klicken und dann Folgendes auswählen: +1: („+1“). Dadurch wird vermieden, dass eine unbrauchbare Benachrichtigung an alle Personen gesendet wird, die dieses Problem abonniert haben.

Alle 35 Kommentare

Dies ist immer noch ein Problem mit Angular 1.2.14: http://jsfiddle.net/HVp2J/7/

Als Workaround kann der Modellwert innerhalb eines $ timeout-Handlers festgelegt werden.

$ timeout hilft nicht, das Problem bleibt bestehen.

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

@ Rajat-Chowdhary Entschuldigung, ich hätte ein Codebeispiel einfügen sollen, das zeigt, wie $ timeout als Workaround funktionieren kann: http://jsfiddle.net/fschwiet/YC4av/

Die Problemumgehung ist schwierig, da der Modellwert erst nach dem $ timeout-Rückruf initialisiert werden kann, damit die Problemumgehung funktioniert.

Es scheint, ich habe das Problem gefunden.
Angular setzt den Wert vor dem Einstellen von min, max und step, sodass sich der Bereich anscheinend in der falschen Position befindet. Um das Problem zu lösen, habe ich diese Richtlinie verwendet

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);
            });
        }
    };
});

Hier gibt es die neue Version von ngRange ohne privaten Bereich:

.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);
                }
            });
        }
    };
});

Das ist immer noch ein Problem, oder?

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

Ja +1

Ja, immer noch ein Problem.

Ich habe im Stackoverflow etwas Ähnliches gefragt, wie der Wert einer Eingabe [Bereich] mit AngularJS initialisiert werden kann, wenn der Wert über 100 liegt . Mit 1.4.0-beta.build.3791 ist dieser Fehler immer noch vorhanden.

+1

+1, und es wurde schlimmer, wenn der Eingangsbereich mit einer Eingangsnummer gekoppelt ist.

+1 für dieses Problem

Vor dem gleichen Problem: +1

yep - gleiches Problem +1

das ist grundlegendes html5 - wie ist der status dazu, arbeitet jemand daran?

unter Berücksichtigung dessen: https://github.com/danielcrisp/angular-rangeslider/issues/51
Dabei wird der Schieberegler Fehler:
Ich habe die @ ardf69- Lösung darauf eingestellt:

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, ich habe das gleiche Problem beim Umschalten von [Eingangstyp = Bereich] mit ng-if

Ich bin auch auf dieses Problem gestoßen und habe eine Frage zum "In Angular bindet das Bindungsattribut der Bereichsvariablen _before_ ngModel das value der Eingabe .

Einige Problemumgehungen wurden als Antworten auf Stapelüberlauf veröffentlicht. In meinem Fall wird die DOM-Manipulation mit $inputElement.prop() , um die Werte von min , max und step festzulegen (je nachdem, welche Attribute benötigt werden). Indem ich diese DOM-Manipulation durchführe, bevor das zugrunde liegende <input> value meiner benutzerdefinierten Direktive zum ersten Mal festgelegt wird, vermeide ich das Problem.

Meine träge Art, diesen Fehler zu beheben, bestand darin, die Min / Max- und Schrittwerte durch 100 zu teilen. 300 wird also zu 3,0 usw. und die Werte fallen unter 100. Dann multipliziere ich die Dinge nach Bedarf zurück. Vielleicht ist es für jemanden nützlich.

+1 Das ist sehr nervig.

+1

+1

+1

Ein weiterer fauler Workaround-Hack:

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

+1

Mit der neuen Reaktionsfunktion von GitHub müssen Sie "+1" nicht mehr kommentieren. Stattdessen können Sie Ihr Interesse markieren, indem Sie oben rechts im ersten Kommentar dieser Ausgabe auf „+: smile:“ klicken und dann Folgendes auswählen: +1: („+1“). Dadurch wird vermieden, dass eine unbrauchbare Benachrichtigung an alle Personen gesendet wird, die dieses Problem abonniert haben.

Ich habe mein Problem mit der Ondrag-Methode gelöst, indem ich das ng-Modell entfernt habe.
Überprüfen Sie diese http://codepen.io/nagarajumusini/pen/BKpGJz

+1

+1

Das Hinzufügen von ng-init zur Eingabe funktioniert für mich, um den Anfangswert festzulegen

<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" />

Gefundene Lösung in:

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

Daran arbeiten wir (endlich). Schließen als Duplikat von https://github.com/angular/angular.js/issues/5892

$ (Dokument) .ready (Funktion () {
angle.element ('. yourclasshere'). val (Wert der Slideronload);
});

Diese jQuery-Problemumgehung funktioniert, sodass Sie beim Laden der Seite einen Wert festlegen können. Der Wert der Schieberegler wird jedoch erst synchronisiert, wenn er berührt wird.

@davedx Vielleicht ist dies der beste Weg, bevor das Problem gelöst ist.

<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>

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen