angular-slider / angularjs-slider

Slider directive for AngularJS 1.X. No dependencies and mobile friendly.
http://angular-slider.github.io/angularjs-slider
MIT License
1.23k stars 498 forks source link

Slider position not set on load #79

Closed rcbgit closed 9 years ago

rcbgit commented 9 years ago

Using angular-fullstack I am setting a slider with the scope value like so:

$scope.sliderValue = 100;

and the markup:

        <rzslider rz-slider-model="sliderValue"
            rz-slider-floor="2"
            rz-slider-hide-limit-labels = "false"
            rz-slider-ceil="100"
            rz-slider-always-show-bar="true"></rzslider>

I am displaying the value of the slider on the page and it is correctly set to 100, but the slider position is stuck at 0 until i click on it, then it jumps up to where it's supposed to be.

rsrikanth080 commented 7 years ago

Sure guys! Will make a fiddle and share. @ValentinH so m not using any popup. its just a block which i show and hide on click of other elements. dom is being created just like other elements.

marcinn commented 7 years ago

As I said earlier - depending on rzSliderForceRender IS a workaround and it causes more problems than benefits it gives (a nice look). Drawing/positioning a slider should be done other way.

ValentinH commented 7 years ago

@marcinn Yes it's a workaround but even after more than a year maintaining this library I couldn't find a better solution... Again contributions are always welcome.

@rsrikanth080 I said "popup", but I just meant that you should call rzSliderForceRender after you show the slider.

rsrikanth080 commented 7 years ago

@ValentinH - https://jsfiddle.net/0wa8Lyj5/1/

ValentinH commented 7 years ago

A few problems there: 1) there is no rz-slider-step attribute in this library, you should set the step in the options 2) you swap floor and ceil values

Demo: https://jsfiddle.net/syxa1k0r/

rsrikanth080 commented 7 years ago

@ValentinH @mjknight50 Its working, As you guys suggested show trigger broadcast when the slider is in visible dom. Thanks guys. I apologize for the stupid question.

ValentinH commented 7 years ago

No worries it's always good to learn and no question is stupid while learning! :)

lu-ctrl-z commented 7 years ago

I have same issue but here my solution.

CSS:

.tab-content.fixTabsAndSlider > .tab-pane{ display: block; height: 0px; overflow: hidden; } .tab-content.fixTabsAndSlider > .tab-pane.active{ display: block; height: auto; overflow: visible; }

html: add class fixTabsAndSlider to div tab-content

johnico commented 7 years ago

happens to me when fade in and fade out the page also with your examples

https://github.com/angular-slider/angularjs-slider/issues/515

ValentinH commented 7 years ago

Did the fix mentioned above work for you?

jdwilemo commented 7 years ago

I have a uib-carousel with a slider in each slide as part of an HTML template, and while the sliders are rendering properly, I am getting a slow drag into each slide instead of a snappy switch.

In order to force rerender the slide, I call the timeout on each slide click like so: <div uib-carousel ng-click="$ctrl.refreshSlider()">

My refresh function is:

this.refreshSlider = function() {
      var $ctrl = this;
      this._$scope.$$postDigest(function () {
        $ctrl._$scope.$broadcast('rzSliderForceRender')
      });
    }

I only have around 20 total sliders, but is this due to the slide waiting for all sliders to rerender? Is there a better way of force rendering sliders when you are dealing with many of them in one page?

To better consolidate this question, the force rerender affects all sliders. Can I call this just when I need it, on the slider that needs to be rerendered?

ValentinH commented 7 years ago

If all sliders are on the same scope, you can't target one specifically when broadcasting the rzSliderForceRender event. You can be more accurate by isolating each slider in its own scope (via a directive) and only broadcast the event on the specific scope.

ValentinH commented 7 years ago

However, I don't think the performance issue comes from the sliders for the following reason: on the demo site, there are more than 30 sliders and I use the refresh on the whole scope in the tas demo and it's not slow...

jdwilemo commented 7 years ago

@ValentinH thanks for the suggestions. I now think it had to do with using the ng-click on the carousel control. I've gotten it to render the controls correctly with no slide lag by doing the following:

this._$scope.$watch(function watchSlides(_$scope){
      return (_$scope.$ctrl.active);
    },
    function handleSlideChange(oldVal, newVal, scope){
      console.log('Id changed to ' + newVal + ' from ' + oldVal);
      scope.$ctrl.refreshSlider();
    });

this.refreshSlider = function() {
      var $ctrl = this;
      this._$timeout(function () {
        $ctrl._$scope.$broadcast('rzSliderForceRender')
      });
    }

In the case someone else has a nested mess like I do.

ValentinH commented 7 years ago

Good to know. Just a little question, why can't you do this.$scope.$watch('$ctrl.active', fn)?

jdwilemo commented 7 years ago

You can if you're only watching one "active" state, but that example is a watered down version of my handleSlideChange which had to watch several dynamic slide + tab combination states. I wasn't sure how to put a watch on only that without breaking it down in the function.

ValentinH commented 7 years ago

OK I get it.

ianldgs commented 7 years ago

I have inserted a debugger; in the $on('rzSliderForceRender') and found that the problem is with resetSlider() -> calcViewDimensions() -> getDimension() -> getBoundingClientRect(). It returns 0 on the properties if the element or parent is hidden.

image

One possible solution is to rely on jQuery, as it does some magic to get the dimensions even if the element is hidden.

Other possible solution is to implement the jQuery magic: https://stackoverflow.com/a/33194373/2502746 https://github.com/jquery/jquery/blob/master/src/css.js#L344

For now, solved by broadcasting rzSliderForceRender. But even inside a $timeout, the $broadcast is called before my element showing up on screen.

Edit: $timeout($broadcast) only works if some $digest is in progress because of some user interaction/ajax

ValentinH commented 7 years ago

I have never met a case where $timeout wasn't enough. If you can provide a demo showing this behaviour, it would be nice.

About the first part of your question, I agree that having to force the rendering is quite annoying and a big source of issues (see the length of this thread). It might be a good idea to use the trick you mentioned when getBoundingClientRect returns width/height = 0.

Do you think you can provide a pull request for this improvement? 🙂

nitingupta4040 commented 6 years ago

Hello Everyone, I tried all options but scale is not rendering properly. The only thing which worked was $timeout(function () { $scope.$broadcast('rzSliderForceRender'); }, 10);. But i do not want to set the time in timeout. Is there a way around?

ZtheLeader commented 6 years ago

@nitingupta4040 Hi, I think there isn't any other possible solution. However, you can decrease the timeout interval to lowest value. Here see my case:

In my case, I used this in my Controller $scope.loadView = function(){ setTimeout(function(){ $scope.$broadcast('rzSliderForceRender'); },1); }

And then in my View (I'm not using tab-ui), I use it as: <div ng-init="loadView()"> <rzslider rz-slider-model="color_slider_pointer.value" rz-slider-options="color_slider_pointer.options"> </rzslider> </div>

And It works like charm! :)

ghost commented 6 years ago

Hi, I tried change ng-show to ng-if and insert this to my init code:

angular.element(document).ready(function () { $scope.$broadcast('rzSliderForceRender'); });

and maybe it would help