Custom IonicModal not hide at right position

By : Imran
Source: Stackoverflow.com
Question!

I have made my custom ionicModal Popup by change the width and height. However I got problems to handle the right position when the modal hide. See my snippet for more clear.

My expected output will be ionicModal hide at bottom to '0' regardless of modal size.

var myApp = angular.module('MyApp',['ionic','ngCordova']);
myApp.controller('HomeCtrl',function($scope, $ionicModal){
  
       $ionicModal.fromTemplateUrl('my-modal.html', {
             scope: $scope,
             animation: 'slide-in-up'
     }).then(function(modal) {
     $scope.modal = modal;
  });
  
  
  $scope.openModal = function() {
     $scope.modal.show();
  };
  
  $scope.home = function ()
  {
    $scope.modal.hide();
    }
});
body
{
  background-color:#f3f3f3;
  }
.modalEduLevel
{
    width: 90%; 
    height: 80%; 
    min-height: 0; 
    max-height: 250px; 
    top: 20%; 
    left: 5%; 
    right: 5%; 
    bottom: 20%;
    border-radius:5px;
    border:2px solid gold;
}
.bg-gold
{
    background-color: #ffd70080;
}
.button-level
{
    background-color: white;
    border: 1px solid purple;
    color: purple;
    font-size: 1.3em;
}
.button-level:hover, .button-level:active
{
    background-color: purple;
    color:white !important;
}
<link href="http://code.ionicframework.com/1.3.1/css/ionic.css" rel="stylesheet"/>
<script src="http://code.ionicframework.com/1.3.1/js/ionic.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-cordova/0.1.27-alpha/ng-cordova.js"></script>
<div ng-app="MyApp" ng-controller="HomeCtrl">
<script id="my-modal.html" type="text/ng-template">
<ion-modal-view class="modalEduLevel">
    <ion-pane class="padding bg-gold">
        Select your education level
        <br/>
        <br/>
        <button ng-click="home()" class="button button-block button-level">
            Level 1
        </button>
        <button ng-click="home()" class="button button-block button-level">
            Level 2
        </button>
        <button ng-click="home()" class="button button-block button-level">
            Level 3
        </button>
    </ion-pane>
</ion-modal-view>
</script>
<button ng-click="openModal()">Open</button>
</div>

By : Imran


Answers

I would say you can do it with setting this simple CSS declaration:

.slide-in-up.ng-leave {
  -webkit-transform: translate3d(0px, 500%, 0px);
  transform: translate3d(0px, 500%, 0px);
}

Ionic sets the ng-leave class to every element that gets removed/hidden etc. The default transform for slide-in-up with ng-leave is transform: translate3d(0px, 100%, 0px); which is the same as when it enters ng-enter. By setting this to 500% it will be surely removed all the way to the bottom. You can do this same with the ng-enter class if you would like the animation to be similar in both cases. You can also overwrite the transition timing if you wish with a declaration like this:

.slide-in-up.ng-leave, .slide-in-up > .ng-leave {
  -webkit-transition: all ease-in-out 450ms;
  transition: all ease-in-out 450ms;
}

var myApp = angular.module('MyApp', ['ionic', 'ngCordova']);
myApp.controller('HomeCtrl', function($scope, $ionicModal) {

  $ionicModal.fromTemplateUrl('my-modal.html', {
    scope: $scope,
    animation: 'slide-in-up'
  }).then(function(modal) {
    $scope.modal = modal;
  });


  $scope.openModal = function() {
    $scope.modal.show();
  };

  $scope.home = function() {
    $scope.modal.hide();
  }
});
body {
  background-color: #f3f3f3;
}
.modalEduLevel {
  width: 90%;
  height: 80%;
  min-height: 0;
  max-height: 250px;
  top: 20%;
  left: 5%;
  right: 5%;
  bottom: 20%;
  border-radius: 5px;
  border: 2px solid gold;
}
.slide-in-up.ng-leave {
  -webkit-transform: translate3d(0px, 500%, 0px);
  transform: translate3d(0px, 500%, 0px);
}
.bg-gold {
  background-color: #ffd70080;
}
.button-level {
  background-color: white;
  border: 1px solid purple;
  color: purple;
  font-size: 1.3em;
}
.button-level:hover,
.button-level:active {
  background-color: purple;
  color: white !important;
}
<link href="http://code.ionicframework.com/1.3.1/css/ionic.css" rel="stylesheet" />
<script src="http://code.ionicframework.com/1.3.1/js/ionic.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-cordova/0.1.27-alpha/ng-cordova.js"></script>
<div ng-app="MyApp" ng-controller="HomeCtrl">
  <script id="my-modal.html" type="text/ng-template">
    <ion-modal-view class="modalEduLevel">
      <ion-pane class="padding bg-gold">
        Select your education level
        <br/>
        <br/>
        <button ng-click="home()" class="button button-block button-level">
          Level 1
        </button>
        <button ng-click="home()" class="button button-block button-level">
          Level 2
        </button>
        <button ng-click="home()" class="button button-block button-level">
          Level 3
        </button>
      </ion-pane>
    </ion-modal-view>
  </script>
  <button ng-click="openModal()">Open</button>
</div>

EDIT:

Here's a demo for you of a custom slide function in the modal.

var myApp = angular.module('MyApp', ['ionic', 'ngCordova']);
myApp.controller('HomeCtrl', function($scope, $ionicModal) {

  $ionicModal.fromTemplateUrl('my-modal.html', {
    scope: $scope,
    animation: 'custom-slide'
  }).then(function(modal) {
    $scope.modal = modal;
  });


  $scope.openModal = function() {
    $scope.modal.show();
  };

  $scope.home = function() {
    $scope.modal.hide();
  }
});
body {
  background-color: #f3f3f3;
}
.modalEduLevel {
  width: 90%;
  height: 80%;
  min-height: 0;
  max-height: 250px;
  top: 20%;
  left: 5%;
  right: 5%;
  bottom: 20%;
  border-radius: 5px;
  border: 2px solid gold;
}
.bg-gold {
  background-color: #ffd70080;
}
.button-level {
  background-color: white;
  border: 1px solid purple;
  color: purple;
  font-size: 1.3em;
}
.button-level:hover,
.button-level:active {
  background-color: purple;
  color: white !important;
}
.custom-slide {
  top: 100% !important;
  opacity: 0 !important;
}
.custom-slide.ng-enter-active {
  top: 20% !important;
  opacity: 1 !important;
  transition: opacity 150ms ease-in-out, top 350ms cubic-bezier(0.17, 0.04, 0.03, 0.94);
}
.custom-slide.ng-leave {
  top: 100%;
  opacity: 0;
  transition: opacity 450ms ease-in-out, top 350ms cubic-bezier(0.17, 0.04, 0.03, 0.94);
}
.custom-slide.ng-leave .button-level:hover,
.custom-slide.ng-leave .button-level:active {
  background-color: white;
  color: purple !important;
}
<link href="https://code.ionicframework.com/1.3.1/css/ionic.css" rel="stylesheet" />
<script src="https://code.ionicframework.com/1.3.1/js/ionic.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-cordova/0.1.27-alpha/ng-cordova.js"></script>
<div ng-app="MyApp" ng-controller="HomeCtrl">
  <script id="my-modal.html" type="text/ng-template">
    <ion-modal-view class="modalEduLevel">
      <ion-pane class="padding bg-gold">
        Select your education level
        <br/>
        <br/>
        <button ng-click="home()" class="button button-block button-level">
          Level 1
        </button>
        <button ng-click="home()" class="button button-block button-level">
          Level 2
        </button>
        <button ng-click="home()" class="button button-block button-level">
          Level 3
        </button>
      </ion-pane>
    </ion-modal-view>
  </script>
  <button ng-click="openModal()">Open</button>
</div>

By : thepio


In addition to the static casting that you've now added to your question, you can make the mapping easier / more explicit by setting the values in equivalent enums using the values from a previous enum:-

enum Enum1
{
    a = 1,
    b = 2,
};

enum Enum2
{
    z = a,
    y = b
};

And a way to collapse template into only needing to specify target...

template <typename targettype>
class Converter
{
    public:
    template<typename sourceType>
    static targettype Convert(sourceType from)
    {
        return static_cast<targettype>(from);
    }
};

callable as:-

Converter<Enum2>::Convert(someEnum1);
By : ROX


C++11 solution:

#include <type_traits>

template<typename From, typename To>
To map(From e) {
    return static_cast<To>(
        static_cast<typename std::underlying_type<To>::type>(
        static_cast<typename std::underlying_type<From>::type>(e)));
}

This casting cascade is very explicit and supports enum classes.

For older C++ versions and for enums without class, static_cast<Enum2>(e) would suffice.

Edit:

With template specialization, you can use map without specifying any types explicitly:

enum class Enum1: int {A, B, C, D};
enum class Enum2: char {A1, B1, C1, D1};

template<typename T>
struct target_enum {
};

template<>
struct target_enum<Enum1> {
    typedef Enum2 type;
};

template<typename From>
typename target_enum<From>::type map(From e) {
    typedef typename target_enum<From>::type To;
    return static_cast<To>(
        static_cast<typename std::underlying_type<To>::type>(
        static_cast<typename std::underlying_type<From>::type>(e)));
}

You can then call map(Enum1::A). Also works with simple, non-class enums.

By : flyx


This video can help you solving your question :)
By: admin