Angular.js: ng-model tidak menetapkan nilai awal dan posisi input [type = range]

Dibuat pada 18 Mar 2014  ·  35Komentar  ·  Sumber: angular/angular.js

Pada dasarnya, input rentang disiapkan dengan nilai awal menggunakan ng-model. Nilai sebenarnya dari elemen HTML, dan posisi slider rentang, salah. Saya berharap posisi slider dan nilai input html selaras dengan variabel model.

Ini adalah repro: http://jsfiddle.net/fschwiet/HVp2J/

Diverifikasi di chrome dan firefox yang berjalan di Windows 8.

Saya melihat ada masalah lain yang dibuka untuk input [type = range], tidak jelas mereka terkait.

forms moderate duplicate broken expected use bug

Komentar yang paling membantu

Dengan fitur Reaksi baru GitHub, Anda tidak perlu lagi berkomentar "+1". Alih-alih, Anda dapat menandai minat Anda dengan mengeklik “+: senyuman:” di kanan atas komentar pertama dalam masalah ini, lalu memilih: +1: (“+1”). Ini untuk menghindari pengiriman pemberitahuan yang tidak berguna kepada semua orang yang berlangganan masalah ini.

Semua 35 komentar

Ini masih menjadi masalah dengan Angular 1.2.14: http://jsfiddle.net/HVp2J/7/

Sebagai solusinya, seseorang dapat menyetel nilai model dalam $ timeout handler.

$ timeout tidak membantu, masalah tetap ada.

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

@ Rajat-Chowdhary Maaf, saya seharusnya menyertakan contoh kode yang menunjukkan bagaimana $ timeout dapat berfungsi sebagai solusi: http://jsfiddle.net/fschwiet/YC4av/

Solusi tersebut terasa tidak pasti karena nilai model tidak dapat diinisialisasi hingga $ timeout callback agar solusi tersebut berfungsi.

Sepertinya saya menemukan masalahnya.
Angular mengatur nilai sebelum mengatur min, max dan step sehingga sepertinya range berada pada posisi yang salah. Untuk mengatasi masalah tersebut saya menggunakan arahan ini

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

Di sini ada versi baru ngRange tanpa ruang lingkup pribadi:

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

ini masih menjadi masalah, bukan?

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

Ya +1

Ya, masih menjadi masalah.

Saya menanyakan sesuatu yang serupa di stackoverflow Bagaimana cara menginisialisasi nilai input [range] menggunakan AngularJS ketika nilainya lebih dari 100 . Menggunakan 1.4.0-beta.build.3791 bug ini masih ada.

+1

+1, dan menjadi yang terburuk ketika kisaran masukan digabungkan dengan nomor masukan.

1 untuk masalah ini

Menghadapi masalah yang sama: +1

ya - masalah yang sama +1

ini adalah html5 dasar - apa statusnya, apakah ada yang mengerjakan ini?

mempertimbangkan ini: https://github.com/danielcrisp/angular-rangeslider/issues/51
di mana Error: ngModel: slider range
saya menyesuaikan solusi @ ardf69 untuk ini:

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, Saya memiliki masalah yang sama saat mengganti [input type = range] dengan ng-if

Saya juga mengalami masalah ini, dan menulis pertanyaan Stack Overflow tentang hal itu, “Di Angular, atribut bind dari variabel lingkup _before_ ngModel mengikat input value . Pertanyaan tersebut mencakup cuplikan kode yang dapat dijalankan yang mereproduksi masalah ini.

Beberapa solusi telah diposting sebagai jawaban di Stack Overflow. Yang berlaku untuk kasus saya melibatkan penggunaan manipulasi DOM dengan $inputElement.prop() untuk menetapkan nilai min , max , dan step (atribut mana pun yang diperlukan). Dengan melakukan manipulasi DOM ini sebelum arahan kustom saya yang mendasari <input> value disetel pertama, saya menghindari masalah.

Cara malas saya untuk mengatasi bug ini adalah dengan membagi nilai min / max dan langkah dengan 100. Jadi 300 menjadi 3,0, dll. Dan nilainya jatuh di bawah 100. Kemudian saya mengalikan semuanya sesuai kebutuhan. Mungkin itu berguna bagi seseorang.

+1 Ini sangat mengganggu.

+1

+1

+1

Peretasan solusi malas lainnya:

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

+1

Dengan fitur Reaksi baru GitHub, Anda tidak perlu lagi berkomentar "+1". Alih-alih, Anda dapat menandai minat Anda dengan mengeklik “+: senyuman:” di kanan atas komentar pertama dalam masalah ini, lalu memilih: +1: (“+1”). Ini untuk menghindari pengiriman pemberitahuan yang tidak berguna kepada semua orang yang berlangganan masalah ini.

Saya telah memecahkan masalah saya menggunakan metode ondrag dengan menghapus ng-model.
periksa http://codepen.io/nagarajumusini/pen/BKpGJz ini

+1

+1

Menambahkan ng-init ke input berfungsi bagi saya untuk menyetel nilai awal

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

Solusi yang ditemukan di:

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

Kami sedang mengerjakan ini (akhirnya). Ditutup sebagai duplikat dari https://github.com/angular/angular.js/issues/5892

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

solusi jQuery ini berfungsi sehingga Anda dapat mengatur nilai saat halaman dimuat tetapi apa pun nilai kontrol slider tidak akan disinkronkan sampai disentuh.

@davedx Mungkin ini adalah cara terbaik sebelum masalah diselesaikan.

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

Apakah halaman ini membantu?
0 / 5 - 0 peringkat