Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slider position not set on load #79

Closed
rcbgit opened this issue Jul 11, 2015 · 72 comments
Closed

Slider position not set on load #79

rcbgit opened this issue Jul 11, 2015 · 72 comments

Comments

@rcbgit
Copy link

rcbgit commented Jul 11, 2015

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.

@soee
Copy link

soee commented Jul 13, 2015

I can confirm this issue (using Angular 1.4.x).

Update: if i resize my window, slider is updated and renders as it should. My problem might be rleated to the fact that i'm using angular-ui tabs and probably i have to use somehow:

$scope.$broadcast('reCalcViewDimensions');

@rcbgit
Copy link
Author

rcbgit commented Jul 13, 2015

I also see the slider render correctly when I resize.

Still no fix. Let me know if you come up with anything.

Thanks!

@soee
Copy link

soee commented Jul 14, 2015

Hi @rcbgit,

as i mentioned before i am using it inside tabs (ui-bootstrap) so the tab content is loaded when we select tab and because of this the sliders aren't updated as they should i think. What i do is to use tab 'select' attribute to call my custom function:

<tabset>
    <tab select="ctrl.broadcast()">
        <tab-heading>Heading</tab-heading>
        @include('_partials.form_tabs_general')
    </tab>
    ...
</tabset>

and in my controller:

function broadcast() {
    setTimeout(function(){
        $scope.$broadcast('reCalcViewDimensions');
    }, 10);
}

In some cases it is better to use Angular's $timeout service instead of native setTimeout.

@bernardmoes
Copy link

I can also confirm this issue.
It doesn't work in combination with the following Jquery:

$(document).ready(function () {
            $('.filterButton').click(function (e) {
                e.preventDefault();
                $('.filterButton').removeClass('on');
                $('.filterContent').slideUp('normal');
                if ($(this).next().is(':hidden') == true) {
                    $(this).addClass('on');
                    $(this).next().slideDown('normal');
                }
            });
            $('.filterContent').hide();
        });

@bdteo
Copy link

bdteo commented Jul 19, 2015

I also experienced exactly what OP described. This repo however seems to be dead anyway.

@mansa-dev
Copy link

Yes same issue here. But repo seems to be abandoned

@sarbjeetsingh
Copy link

I also got the same issue, i used
setTimeout(function(){
$scope.$broadcast('reCalcViewDimensions');
},500)

@ValentinH
Copy link
Member

Indeed, using $scope.$broadcast('reCalcViewDimensions'); is the solution. This problem is due that when the slider is instantiated, the view is not visible and so it cannot be rendered properly.

This particular problem with tabs is mentionned here: https://github.com/rzajac/angularjs-slider#slider-events .
I have also experienced the issue when using a slider inside a angular-ui dropdown.

@aphanor
Copy link

aphanor commented Jul 29, 2015

Hey guys, I am having the same issue and I tried adding $scope.$broadcast('reCalcViewDimensions'); but it didn't work. Here is live working example:

http://ec2-52-16-54-212.eu-west-1.compute.amazonaws.com/test.html

The slider is on page "2".

Am I doing anything wrong?

@ValentinH
Copy link
Member

Please provide a Fiddle that present the strict minimum of your problem. I don't want to go visiting a random page which can contain anything (virus?)...

@aphanor
Copy link

aphanor commented Jul 29, 2015

Sure, here is an example on Codepen: http://codepen.io/anon/pen/QbJmja

@ValentinH
Copy link
Member

There you go: http://codepen.io/ValentinH/pen/yNQKXR?editors=001

You had several Angular-related problem:

Finally, in your example, it also works without wrapping the $scope.$broadcast('reCalcViewDimensions') with $timeout but it depends on the step plugin sequencing. To be sure that it is always called after the view is shown, use $timeout so the broadcast is called in the next JS loop.

@aphanor
Copy link

aphanor commented Jul 29, 2015

Awesome, thanks a lot for your help, it's much appreciated!

@gpolyn
Copy link

gpolyn commented Sep 24, 2015

Per the OP's use context, and attempting the fix proposed from Jul 29, this still doesn't work.

Failing an example with tabs, I warn others about this integration!

@ValentinH
Copy link
Member

Since I'm in a good mood today, there is your example:
Slider inside Angular UI tabs: http://jsfiddle.net/7w755fLv/

I'm adding it to the doc...

@gpolyn
Copy link

gpolyn commented Sep 24, 2015

Yes, that does better address it, though the rendering is triggered by tab select and I think I notice the slider's correcting action, visually.

Based on review of Angular-UI Bootstrap tab issues, I might expect challenges for the embedding of any directive in tab content panes. Therefore, my proposal to anyone (perhaps it is already familiar to most) is to confirm their chosen tab directive works with any directives planned for use in tab panes.

@ValentinH
Copy link
Member

You will get issues with any widgets that show/hide content dynamically such as tabs, popover or even ng-show.
The problem is that the directive you place inside the content, such as this slider, does not have an efficient way to detect when it becomes visible. So if this directive needs to compute the width/height/position of its parent, you will need to trigger a refresh event manually.

@pushpendra18
Copy link

Hi All,

I have faced the same issue inside accordion my slider not initializing.
Finally ValentinH solution guide me in right path.
Below is the code.

Calling refreshSlider() in ng-click of the accordion div .

HTML:

<form name="myform">
    <div class="panel-group flatPannels filterGroup" id="accordion">
        <div class="panel panel-default filterStyle" ng-click="refreshSlider()">
            <div class="panel-heading">
                <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" data-target="#collapseFour">
                    <h4 class="panel-title">  myslider<i class="indicator glyphicon glyphicon-chevron-down pull-right"></i></h4>
                </a>
            </div>
            <div id="collapseFour" class="panel-collapse collapse">
                <div class="panel-body">
                    <label class="title" ></label>
                    <div class="sliderInputWrapepr">
                        <input type="number"
                               placeholder="{{ 'enter'  }}"
                               ng-change="chklim($event)"
                               ng-minlength="1"
                               ng-maxlength="3"
                               ng-min="aslider.floor"
                               ng-max="aslider.ceil"
                               name="inputvalMax" class="sliderinput" ng-class="{'err-txtbox':!searchFilterForm.inputvalMax.$valid}" ng-model="aslider.value1" required /><br />
                    </div>
                    <rzslider rz-slider-floor="aslider.floor"
                              rz-slider-ceil="aslider.ceil"
                              rz-slider-model="aslider.value"
                              rz-slider-step="1"
                              rz-slider-always-show-bar="true"
                              rz-slider-tpl-url="rzSliderTpl.html"
                              rz-slider-on-change="searchval();"></rzslider>
                </div>
            </div>
        </div>           
    </div>
</form>

Angular:

 $scope.refreshSlider = function () {
    $timeout(function () {
        $scope.$broadcast('rzSliderForceRender');
    });
};

@Luddinus
Copy link

Luddinus commented Nov 3, 2015

With ng-if works, not with ng-show

@matortheeternal
Copy link

@Luddinus ng-if works but it doesn't maintain slider values after you hide and show it again.

@ValentinH
Copy link
Member

If the slider is inside a div toggled with ng-if, it is destroyed on each hide: this is normal since ng-if destroys its content.

You need to save the slider value in the parent's scope then or in a service.

@mjknight50
Copy link

mjknight50 commented Apr 25, 2016

Hi Valentin,
I have the same issue if you wouldn't mind taking a look, please?

https://jsfiddle.net/mjknight50/hmap4qj7/

I have tried all of the suggestions I have seen you post so far, but the initial slider position isn't setting correctly until I resize the screen or until I click on the slider.

@ValentinH
Copy link
Member

@mjknight50 You need to send the following event when the slider becomes visible:

$scope.$broadcast('rzSliderForceRender');

I can't really help more because your example is complex and generating a lot of errors that are not linked to the slider.

@mjknight50
Copy link

mjknight50 commented Apr 25, 2016

Thanks Valentin...
I added this, which fixed it:

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

@mjknight50
Copy link

mjknight50 commented Dec 20, 2016

@rsrikanth080 I am using controllerAs with no problem. As @ValentinH said, if you have a more complete example, it would help.

Here is how I am doing that same block you listed:

//in theory, only one of these should be needed, to force the render, but both are needed in my testing

$timeout(function () { $scope.$broadcast('rzSliderForceRender'); }, 170);

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

@ValentinH
Copy link
Member

When do you call $timeout? BTW, we need code to understand what you do. The best so we can help you would be to create a JSFiddle only showing the issue and the code for it.

@mjknight50
Copy link

@rsrikanth080 - Please be considerate of our time. Searching through your source code to help you isn't ideal. A JSFiddle would be better and would probably also help you by isolating the issue.

@ValentinH
Copy link
Member

Please, I won't help you if you don't provide materials! I'm not supposed to go and read all your code, people are are contributing on their free time. If you want enterprise support, then pay somebody for that.

@ValentinH
Copy link
Member

However, your issue is probably due to the fact the you must call rzSliderForceRender after your popup is shown (as done on the uib-modal demo on our demo page).

@mjknight50
Copy link

I agree with @ValentinH; the issue is that when your shopService comes back with prices, you must then call rzSliderForceRender to reinitialize the slider. You can use my sample code from above to do this rendering.

@rsrikanth080
Copy link

rsrikanth080 commented Dec 20, 2016

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

marcinn commented Dec 20, 2016

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
Copy link
Member

ValentinH commented Dec 20, 2016

@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
Copy link

@ValentinH
Copy link
Member

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

@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
Copy link
Member

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

@lu-ctrl-z
Copy link

lu-ctrl-z commented Jan 17, 2017

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

johnico commented Mar 27, 2017

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

#515

@ValentinH
Copy link
Member

Did the fix mentioned above work for you?

@jdwilemo
Copy link

jdwilemo commented Apr 19, 2017

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
Copy link
Member

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
Copy link
Member

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

@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
Copy link
Member

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

@jdwilemo
Copy link

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
Copy link
Member

OK I get it.

@ianldgs
Copy link

ianldgs commented Jul 18, 2017

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
Copy link
Member

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

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

ZtheLeader commented Dec 28, 2017

@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
Copy link

ghost commented Aug 21, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests