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

Failed to use delegate-handle for several instances of ion-slide-box #1865

Closed
MaximShoustin opened this issue Jul 27, 2014 · 16 comments
Closed
Milestone

Comments

@MaximShoustin
Copy link

I have 3 ion-slide-box. Everyone has 3 items.

I created two buttons Next and back to simulate sliding by pressing them.

However delegate-handle doesn't work. I get:

Delegate for handle "slider1" could not find a corresponding element with delegate-handle="slider1"! next() was not called!

Sounds like delegate-handle doesn't register properly the instance ids.

This is what I have so far:

scope.nextSlider = function(sliderId){
         $timeout(function(){
             $ionicSlideBoxDelegate.$getByHandle(sliderId).next();
      }, 1000);       
      }

       scope.prevSlider = function(sliderId){         
         $timeout(function(){
             $ionicSlideBoxDelegate.$getByHandle(sliderId).previous();
      }, 1000);         
      } 

Template

 <ion-slide-box delegate-handle="{{sliderId}}" 
                       on-slide-changed="slideHasChanged(index)" 
                       show-pager="false">
      <ion-slide ng-repeat="color in colors">        
             <!-- -->
        </ion-slide>
    </ion-slide-box>

And this is a DEMO I play with

The issue was posted in Ionic Forum

@mlopez-firstfactory
Copy link

I already posted a solution in the ionic forum, but it isn't in the repo yet, so I'll just copy what I posted back there:

I was having this issue as well, the problem is I am generating the slide boxes dynamically, which means the delegate-handles are supposed to be generated by angular, when I logged the $ionicSlideBoxDelegate, I could see that it had six instances but their delegate-handles weren't being interpolated, they had the angular code as a string: "slider-{{id}}", and I kept getting this error:

Delegate for handle "slider-4" could not find a corresponding element with delegate-handle="slider-4"! enableSlide() was not called!
Possible cause: If you are calling enableSlide() immediately, and your element with delegate-handle="slider-4" is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to enableSlide() and try again.

For this to work, I had to modify the slidebox source code, what I did was to add the delegateHandle attribute in the scope, so this way it is interpolated.

Like this:

scope: {
...,
delegateHandle: '@'
}

and then I changed this line of code:

var deregisterInstance = $ionicSlideBoxDelegate._registerInstance(slider, $attrs.delegateHandle);

to:

var deregisterInstance = $ionicSlideBoxDelegate._registerInstance(slider, $scope.delegateHandle);

My delegate-handles are now being interpolated and I can also access the handles correctly.

Not sure if this is a "good" solution, hope it helps!

@MaximShoustin
Copy link
Author

Good catch. I don't know if its good solution, anyways Ionic team must run regression tests and include these changes as bug fix. Thanks,

@mhartington
Copy link
Contributor

@ajoslin, want to keep this mind with the slide-box rework?

@adamdbradley adamdbradley added this to the 1.0.0-rc1 milestone Aug 28, 2014
@mikesurowiec
Copy link

This is terrible, but for anyone who must use a generated delegate handle, this is a temporary solution where you don't have to hack the source.

In your template:

...
<ion-content delegate-handle="WILLREPLACE" on-scroll="onScroll()">
...

In your corresponding directive:

...
compile: function ($element, attrs) {
   attrs.generatedHandle = Math.random().toString(36).substring(7);
   $element[0].innerHTML = $element[0].innerHTML.replace('WILLREPLACE', attrs.generatedHandle);
   return postLink;
}
...

ajoslin added a commit that referenced this issue Oct 8, 2014
Closes #2336. Closes #2317. Closes #2290. Closes #2228. Closes #2067.
Closes #1890. Closes #1865. Closes #1850. Closes #1755. Closes #1688.
Closes #1578. Closes #1501. Closes #1353. Closes #1342. Closes #782.
Closes #416. Closes #2288.

BREAKING CHANGE: The slideBox's API has undergone many changes.

- **`<ion-slide-box>`** attributes have changed (see
  [documentation](http://ionicframework.com/docs/api/directive/ionSlideBox)):

  * `active-slide` has changed to `selected`. Change your code from
  this:

    ```html
    <ion-slide-box active-slide="activeSlideIndex"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box selected="activeSlideIndex"></ion-slide-box>
    ```

  * `does-continue` has changed to `loop`.  Change your code from this:

    ```html
    <ion-slide-box does-continue="shouldLoop"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box loop="shouldLoop"></ion-slide-box>
    ```

  * `auto-play` and `slide-interval` have been merged into `auto-play`.
  Change your code from this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="true" slide-interval="1000">
    </ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false" slide-interval="1000">
    </ion-slide-box>
    ```

    To this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="1000"></ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false"></ion-slide-box>
    ```

  * `show-pager` and `pager-click` have been removed. Use
  a child `<ion-slide-pager>` element. See the [`ion-slide-pager`
  documentation](http://ionicframework.com/docs/api/directive/ionSlidePager).
  Change your code from this:

  ```html
  <!-- pager using default click action -->
  <ion-slide-box show-pager="true">
  </ion-slide-box>
  <!-- pager with custom click action -->
  <ion-slide-box show-pager="true" pager-click="doSomething(index)">
  </ion-slide-box>
  ```

  To this:

  ```html
  <ion-slide-box>
    <!-- pager using default click action -->
    <ion-slide-pager></ion-slide-pager>
  </ion-slide-box>
  <ion-slide-box>
    <!-- pager with custom click action -->
    <ion-slide-pager ng-click="doSomething(index)"></ion-slide-pager>
  </ion-slide-box>
  ```

- **`$ionicSlideBoxDelegate`** methods have changed (see
  [documentation](http://ionicframework.com/docs/api/service/$ionicSlideBoxDelegate)):

  - `update()` has been removed. slideBox updates on its own now.

  - `stop()` has been removed. See `autoPlay()` below.

  - `start()` hass been removed. See `autoPlay()` below.

  - `slide(newIndex[, speed])` has been renamed to `select(newIndex[,
    speed]);

  - `currentIndex()` has been renamed to `selected()`.

  - `slidesCount()` has been renamed to `count()`.

  - New method `$ionicSlideBoxDelegate.autoPlay()`. Change your code
    from this:

    ```js
    // stop auto sliding
    $ionicSlideBoxDelegate.stop();
    // later... start auto sliding
    $ionicSlideBoxDelegate.start();
    ```

    To this:

    ```js
    var autoPlaySpeed = 3000; //wait 3000 seconds between changing slide
    // stop auto sliding
    $ionicSlideBoxDelegate.autoPlay(false);
    // later... start auto sliding
    $ionicSlideBoxDelegate.autoPlay(autoPlaySpeed);
    ```

  - `previous()` now returns the index of the previous slide and does
    not select. Change your code from this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.previous();
    ```

    To this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.previous() );
    ```
  - `next()` now returns the index of the next slide and does
    not select. Change your code from this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.next();
    ```

    To this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.next() );
    ```
@ajoslin ajoslin closed this as completed in 7ef9ad7 Oct 8, 2014
@ajoslin ajoslin removed the ready label Oct 8, 2014
ajoslin added a commit that referenced this issue Oct 10, 2014
Closes #2336. Closes #2317. Closes #2290. Closes #2228. Closes #2067.
Closes #1890. Closes #1865. Closes #1850. Closes #1755. Closes #1688.
Closes #1578. Closes #1501. Closes #1353. Closes #1342. Closes #782.
Closes #416. Closes #2288.

BREAKING CHANGE: The slideBox's API has undergone many changes.

- **`<ion-slide-box>`** attributes have changed (see
  [documentation](http://ionicframework.com/docs/api/directive/ionSlideBox)):

  * `active-slide` has changed to `selected`. Change your code from
  this:

    ```html
    <ion-slide-box active-slide="activeSlideIndex"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box selected="activeSlideIndex"></ion-slide-box>
    ```

  * `does-continue` has changed to `loop`.  Change your code from this:

    ```html
    <ion-slide-box does-continue="shouldLoop"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box loop="shouldLoop"></ion-slide-box>
    ```

  * `auto-play` and `slide-interval` have been merged into `auto-play`.
  Change your code from this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="true" slide-interval="1000">
    </ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false" slide-interval="1000">
    </ion-slide-box>
    ```

    To this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="1000"></ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false"></ion-slide-box>
    ```

  * `show-pager` and `pager-click` have been removed. Use
  a child `<ion-slide-pager>` element. See the [`ion-slide-pager`
  documentation](http://ionicframework.com/docs/api/directive/ionSlidePager).
  Change your code from this:

  ```html
  <!-- pager using default click action -->
  <ion-slide-box show-pager="true">
  </ion-slide-box>
  <!-- pager with custom click action -->
  <ion-slide-box show-pager="true" pager-click="doSomething(index)">
  </ion-slide-box>
  ```

  To this:

  ```html
  <ion-slide-box>
    <!-- pager using default click action -->
    <ion-slide-pager></ion-slide-pager>
  </ion-slide-box>
  <ion-slide-box>
    <!-- pager with custom click action -->
    <ion-slide-pager ng-click="doSomething(index)"></ion-slide-pager>
  </ion-slide-box>
  ```

- **`$ionicSlideBoxDelegate`** methods have changed (see
  [documentation](http://ionicframework.com/docs/api/service/$ionicSlideBoxDelegate)):

  - `update()` has been removed. slideBox updates on its own now.

  - `stop()` has been removed. See `autoPlay()` below.

  - `start()` hass been removed. See `autoPlay()` below.

  - `slide(newIndex[, speed])` has been renamed to `select(newIndex[,
    speed]);

  - `currentIndex()` has been renamed to `selected()`.

  - `slidesCount()` has been renamed to `count()`.

  - New method `$ionicSlideBoxDelegate.autoPlay()`. Change your code
    from this:

    ```js
    // stop auto sliding
    $ionicSlideBoxDelegate.stop();
    // later... start auto sliding
    $ionicSlideBoxDelegate.start();
    ```

    To this:

    ```js
    var autoPlaySpeed = 3000; //wait 3000 seconds between changing slide
    // stop auto sliding
    $ionicSlideBoxDelegate.autoPlay(false);
    // later... start auto sliding
    $ionicSlideBoxDelegate.autoPlay(autoPlaySpeed);
    ```

  - `previous()` now returns the index of the previous slide and does
    not select. Change your code from this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.previous();
    ```

    To this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.previous() );
    ```
  - `next()` now returns the index of the next slide and does
    not select. Change your code from this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.next();
    ```

    To this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.next() );
    ```
@manu-pandey
Copy link

Hi,
When will this fix be available? I upgraded to latest (1.0.0-beta 13) available at ionic website but issue still exits in there.

Nightly fixes this issue but I am seeing some other issues with the nightly.

Thanks

@gastonbesada
Copy link

@mhartington Mike, I'm having same issue in 1.0.0-beta.14-nightly-964. Could you please, help to solve this issue?

Thanks!

@danfaber
Copy link

danfaber commented Feb 6, 2015

I had an issue with this and used this workaround which does not involve modifying the ionic source:

Give each slide a unique id which can be an angular binding.
Then you just need to filter on the $ionicScrollDelegate instances collection to get the one which has an element with the id you're looking for on.

Here's a quick copy and paste of my code in case it helps:

 <ion-slide ng-repeat="page in pages" active-slide="page">

            <ion-content id="{{page.name}}">

...

        $scope.getScrollPosition = function (page) {

        var instances = $ionicScrollDelegate["_instances"];

        var instance = _(instances).find(function(ins) {
            return ins.$element[0].id === page.name;
        });

        console.log(JSON.stringify(instance.getScrollPosition()));
    };

@panurge-ws
Copy link

An universal directive to use random-generated delegate-handle (inspired to @mikesurowiec ) :

angular.module('app').directive('randomDelegateHandle', [function () {
  return {
    priority: 1000,
    restrict: 'A',
    compile: function compile(tElement, tAttrs, transclude) {
        tAttrs.$set('delegateHandle', Math.random().toString(36).substring(7));
        return function postLink(scope, iElement, iAttrs, controller) {}
    }
};

}]);

use:

ion-content random-delegate-handle

@steveoc64
Copy link

Still appears to be messy using 1.0.0-rc.1

danfaber's comment above was really useful in working out what the problem is, but the find() fn is not totally portable it seems :(

I just created a very simple service to manage jumping between tabs in my application (which has lots of nested tabs, and breaks quickly using ionic's built in tab delegate functions).

A horrible solution perhaps .... but this is working very reliably for me at the moment, and it bypasses any need to touch the underlying ionic libs. The code below is verbose and non-optimal, but its easy to reason about, and portable.

// A fix for broken ionic tabs delegate

.factory('$tabs', ['$ionicTabsDelegate', function($ionicTabsDelegate) {
  return {
    get: function(handle) {

      var tabs = $ionicTabsDelegate._instances
      var theTab = undefined

      // Manually walk ionic's internal array of tabs, and find the matching tab
      // use angular's built in array iterator for best portability
      angular.forEach(tabs, function(v,k){
        if (v.$$delegateHandle === handle) {
          theTab = v
        }
      })
      return theTab
    },
    select: function(handle,position) {
      console.log('tabs select',handle,position)

      var theTab = this.get(handle)
      if (theTab !== undefined) {
        theTab.select(position)
      }
    }
  }
}])

Usage :

<ion-tabs delegate-handle="MainTabs">
 ....   lots of tabs in here
</ion-tabs>
.controller('myExamplecontroller', ['$tabs', function($tabs) {
    return {
       showFirstTab:  function() {
           $tabs.select('MainTabs',0)
       },
       showSecondTab:  function() {
           $tabs.select('MainTabs',1)
       },
      // etc
    }


}])

@ringo22
Copy link

ringo22 commented May 7, 2015

I think it find a possibility for solve this error "Delegate for handle "my-handle" could not find a corresponding element with delegate-handle..."

This possibility is caused why $ionicSideMenuDelegate.$getByHandle('menuLeftHandle')._instances is a Array

$ionicSideMenuDelegate.$getByHandle('menuLeftHandle')._instances[n]. anyMethod()

@saideldah
Copy link

saideldah commented Jun 27, 2016

Hello
is this issue has been solved?

i still have same problem with generated delegate-handle

this is my code
JS Controller
$scope.swapName = "swap00";
$scope.ds = function (sN) { $ionicSlideBoxDelegate.$getByHandle(sN).enableSlide(false); };
HTML
<ion-slide-box show-pager="false" delegate-handle="{{swapName}}" ng-init="ds(swapName)">
<ion-slide > 1 </ion-slide>
<ion-slide > 2 </ion-slide>
<ion-slide > 3 </ion-slide>
</ion-slide-box>

i get this message:
Delegate for handle "swap00" could not find a corresponding element with delegate-handle="swap00"! enableSlide() was not called!
Possible cause: If you are calling enableSlide() immediately, and your element with delegate-handle="swap00" is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to enableSlide() and try again.

@thepi0
Copy link

thepi0 commented Aug 4, 2016

I had a similar problem and asked it in StackOverflow and got a great temporary solution to the problem. See it at StackOverflow. So basically set and get the delegate-handle by id of the container.

Hopefully this can help someone in the future.

@DHclly
Copy link

DHclly commented Aug 8, 2016

URL:ionicframework
I think we are use in wrong, look at the API , the attr delegate-handle accept value type is string, not expression , but I think the type of string is not suitable.

hope you can understand what I said. ^-^

@yacaeh
Copy link

yacaeh commented Aug 11, 2016

Based on @thepi0 's Link I could solve this problem. For someone who needs help, share code here. You can just put this on your controller.
To get dynamically created index of the slide box like with ng-repeat

    $scope.getSlideBoxDelegateHandle = function(delegateIndex) {
        //get all the instances that ionic scroll delegate is handling
        var instances = $ionicSlideBoxDelegate["_instances"];
        //Create Instance you want to get
        var instance = null;
        for (var index in instances) {
            //set DelegateHandle value with your index
            //Ex) instances[index].$$delegateHandle = "slidebox"+index;
            //or just instances[index].$$delegateHandle = index;
            instances[index].$$delegateHandle = index;
            if (index == delegateIndex) {
                instance = instances[index];
            }
        }
            return instance; //return the instance        
    }

usage
HTML

<div class="list" ng-repeat="myIndex in dynamics> <ion-slide-box delegate-handle="{{myIndex}}">

JS

$scope.slideIndex = $scope.getSlideBoxDelegateHandle(myIndex).currentIndex or anymethod;

@eternalsayed
Copy link

I fixed mine with a custom function with help from @yacaeh 's code above. Basically, instead of comparing indexes, I compared the HTML object of the passed ion-content from the ones available under $ionicScrollDelegate list. Works like charm for me.

function getScrollDelegate(element, $ionicSlideBoxDelegate) {
  var instances = $ionicSlideBoxDelegate["_instances"];
  //Create Instance you want to get
  var instance = null;
  for (var index in instances) {
    //set DelegateHandle value with your index
    //Ex) instances[index].$$delegateHandle = "slidebox"+index;
    //or just instances[index].$$delegateHandle = index;
    instances[index].$$delegateHandle = instances[index].$$delegateHandle || index;
    if (instances[index].$element[0] == element[0]) {
      instance = instances[index];
    }
  }
  return instance; //return the instance
}

And in my directive, I called it like below:

      var $scroll = $('.scroll-content', el.parent());//selector to get the ion-content element in current view
      vm.prevTop = 0; 
      var handle = getScrollDelegate($scroll, $ionicScrollDelegate);//gets the handle
      $scroll.on('scroll', function (e) {
         var pos = handle.getScrollPosition();
         var cl = pos.top>vm.prevTop ?'go-down' :'go-up';
         $(button).removeClass('go-down go-up').addClass(cl);
     })

@ionitron-bot
Copy link

ionitron-bot bot commented Sep 1, 2018

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Sep 1, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests