2
votes

I'm new to angularjs and directives, and I'm actually having troubles with them. I want to create a custom directive to display images in my ionic 1 application.

To achieve this, I need to bind an object ('modal') to be able to link a showModal() function to my parent view; and also an url of the media that I want to display : so, an object and a string.

I use a templateUrl that I configure in my directive. The modal is correctly linked to my parent and template, but I cannot display my image : I get the right url in my scope, controller, but ng-src doesn't load my url (it's empty in my template). I think the issue is related to a bad understanding of the scope behaviour, but I cannot reach a solution.

If you could help me with this problem, I would be very thankful!

Here is some of my code for a better understanding of the problem :

Template :

<div class="modal image-modal transparent">
  <button class="button button-full icon-right ion-close-round" id="button-modal" 
          ng-click="modal.hide()">Close</button>
  <img ng-src="{{url}}" class="fullscreen-image"/>
</div>

Parent view :

<div ng-switch-when="image">
  <a class="item item-icon-left" ng-click="vm.modal.show()">
    <i class="icon ion-android-image"></i>
    {{vm.media.filename}}
  </a>
  <image-displayer url="{{vm.media.url}}" modal="vm.modal"></image-displayer>
</div>

Directive :

    .directive('imageDisplayer', ['$ionicModal', function($ionicModal) {
      return {
        scope: {},
        restrict: 'E',
        replace: true,
        controller: function() {
          console.log(this);
        },
        controllerAs: 'vm',
        bindToController: {
          modal: '=',
          url: '@'
        },
        tempalteUrl: 'components/medias/image-popover.html',
        link: function(scope, element, attr) {
          console.log(scope);
          var url = scope.url;
          var modal = scope.vm.modal;
          modal.show = showModal;
          modal.close = closeModal;
          function showModal() {
            modal.show();
          };

          function closeModal() {
            modal.hide();
          };

          $ionicModal.fromTemplateUrl('components/medias/image-popover.html', {
            animation: 'slide-in-up'})
            .then(function(modalCreated) {
              modal = modalCreated;
            });
        }
      };

Thank you in advance !


EDIT

So I found the solution to my problem : IonicModal creates its own scope, that's why it cannot access my data. To solve the problem I added :

      $ionicModal.fromTemplateUrl('components/medias/image-popover.html', {
        animation: 'slide-in-up'})
        .then(function(modalCreated) {
          modal = modalCreated;
          modal.url = url; //ADDED THIS LINE
        });

It can also be fixed by adding the controller in the html template or the scope as a parameter to the ionic modal in the controller.

2
` modal.show = showModal;modal.close = closeModal;function showModal() {`. showmodal isn't defined at the moment you affect it to modal.show, so your function show is probably undefined and so your code won't work. - Walfrat
@Walfrat Thank you for your help, I found the solution and added it in the post (see the edit) ! - Hisaeri
Note if you find a solution on your own, you can add an answer on your own question. It's even preferred over editing your post adding the solution. - Walfrat
@Walfrat Ok, I will do it ASAP, thanks for the advice! - Hisaeri

2 Answers

2
votes

As you have mentioned the controller alias as controllerAs: 'vm', you should access the url as {{vm.url}} inside the template as below,

<div class="modal image-modal transparent">
  <button class="button button-full icon-right ion-close-round" id="button-modal" 
          ng-click="modal.hide()">Close</button>
  <img ng-src="{{vm.url}}" class="fullscreen-image"/>
</div>

Also, remove the braces from url="{{vm.media.url}} so it will become <image-displayer url="vm.media.url"

Parent view :

<div ng-switch-when="image">
  <a class="item item-icon-left" ng-click="vm.modal.show()">
    <i class="icon ion-android-image"></i>
    {{vm.media.filename}}
  </a>
  <image-displayer url="vm.media.url" modal="vm.modal"></image-displayer>
</div>

Also, you can move all the code from the link function to the controller and access url as this.url inside the controller. So it will be like this, var url = this.url; var modal = this.modal; You don't need actually the link function here.

.directive('imageDisplayer', ['$ionicModal', function($ionicModal) {
      return {
        scope: {},
        restrict: 'E',
        replace: true,
        controller: function() {
          var url = this.url;
          var modal = this.modal;
          //modal.show = showModal; // Is it creating a infinitive call with "showModal"
          modal.close = closeModal;
          /*function showModal() {
            modal.show();
          };*/

          function closeModal() {
            modal.hide();
          };

          $ionicModal.fromTemplateUrl('components/medias/image-popover.html', {
            animation: 'slide-in-up'})
            .then(function(modalCreated) {
              modal = modalCreated;
            });
        },
        controllerAs: 'vm',
        bindToController: {
          modal: '=',
          url: '@'
        },
        tempalteUrl: 'components/medias/image-popover.html'
      };

Note: I have commented the modal.show since its linked to showModal function which is calling again and again modal.show() infinitely.

2
votes

SOLUTION

So I found the solution to my problem : IonicModal creates its own scope, that's why it cannot access my data. To solve the problem I added :

  $ionicModal.fromTemplateUrl('components/medias/image-popover.html', {
    animation: 'slide-in-up'})
    .then(function(modalCreated) {
      modal = modalCreated;
      modal.url = url; //ADDED THIS LINE
    });

It can also be fixed by adding the controller in the html template or the scope as a parameter to the ionic modal in the controller.