AngularJS无法在指令内调用控制器方法

时间:2017-10-22 10:10:13

标签: javascript angularjs ionic-framework angularjs-directive

我正在研究混合Ionic1应用程序,我无法从指令内部调用控制器方法。 问题是在指令中我能够传递控制器的变量(例如变量apps),但是我无法在card-app指令中调用removeCredentials()

我已经尝试了很多方法让它发挥作用,但没有一个能解决问题。我也尝试使用&绑定指令中的控制器方法,但点击指令模板中的X图标不会触发任何内容。

现在代码看起来像这样:

apps.js中的控制器AppsCtrl

angular.module('testprofile')
.controller('AppsCtrl', function($scope, $state, $log, $ionicHistory, $filter, $ionicPopup, UserData, CredentialStoreService, ionicMaterialMotion, ionicMaterialInk, Auth, Effects, CredentialStoreService, Globals, Validations) {

$scope.onlyMyApps = true;
$scope.showNoItems = false;

var translate = $filter('translate');

$scope.apps = [];

$scope.mapAppsFromCredentials = function(credentials) {

    var map = credentials.map(function(cred) {
        /*  app: "App 1"
            appId: 7
            profile: "Default Profile"
            profileId: 0
        */
        var app = UserData.getLocalApp(cred.app);
        if (!app) {
            $log.debug("apps.js::mapAppsFromCredentials - no local app matching credentials: "+JSON.stringify(cred));
            return null;
        }

        var curHelper = UserData.getCurrentAppHelper(app);
        return {
            used: Boolean(cred.used),
            id: app.id,
            title: app.nameApp,
            profile: cred.profile,
            desc: curHelper ? curHelper.name : 'NO HELPER'

        };
    })


    return map;

}

$scope.refresh = function() {
    $log.debug("apps.js::AppsCtrl - REQUEST CREDENTIAL LIST...");
    CredentialStoreService.getCredentialList(
        //ON SUCCESS
        function(response) {
            $log.debug("apps.js::AppsCtrl - ...CREDENTIAL LIST RESPONSE: " + JSON.stringify(response));
            $scope.apps = $scope.mapAppsFromCredentials(response);
            Effects.init();
            $scope.showNoItems = true;
            for (var i = 0; i < $scope.apps.length; i++) {
                if ($scope.apps[i].used) {
                    $scope.showNoItems = false;
                    break;
                }
            }
        },

        //ON ERROR
        function() {
            $log.debug("apps.js::AppsCtrl - ...CREDENTIAL LIST ERROR");
        }
    )
}

$scope.$on("$ionicView.enter", function () {
    $log.debug("apps.js::$ionicView.enter - ENTER");
    $scope.refresh();
});

//REMOVE CREDENTIALS
$scope.removeCredentials = function() {

    $log.debug("app-details.js::removeCredential CONFIRMATION...");
    $ionicPopup.confirm({
        title: translate('Remove Credentials'),
        template: translate('Are you sure you want to delete current credentials') + ' ' + app.nameApp + '?',
        cancelText: translate('No'), // String (default: 'Cancel'). The text of the Cancel button.
        //cancelType: '', // String (default: 'button-default'). The type of the Cancel button.
        okText: translate('Yes'), // String (default: 'OK'). The text of the OK button.
        okType: 'button-energized-900' // String (default: 'button-positive'). The type of the OK button.
    }).then(function(res) {
        if(res) {
            $log.debug("app-details.js::removeCredential CONFIRMED!");
            Auth.askPIN(true)
                .then( function() {
                    CredentialStoreService
                        .removeCredential(
                                        //authenticationProfileName
                                        UserData.getAuthProfile(app).name,
                                        //appProfileName
                                        app.name,
                                        // ON SUCCESS
                                        onRemovedCredential,
                                        // ON ERROR
                                        Globals.onError);

                });




        } else {
            $log.debug("app-details.js::removeCredential REJECTED.");
        }
    });
};

var onRemovedCredential = function() {
    $log.debug("app-details.js::removeCredential CREDENTIALS REMOVED!");
    Effects.showToast(translate('CREDENTIALS REMOVED')+'.');
    $ionicHistory.nextViewOptions({
        disableBack: true
      });
    $state.go('menu.apps', {}, {reload:true});
};

})

inclusions.js中的指令

angular.module('testprofile')

.directive('cardProfile', function() {
  return {
    scope: {
      data:"=cardSource"
    },
    restrict: 'E',
    templateUrl: 'app/templates/card-profile.html'
  };
})


.directive('cardApp', function() {
  return {
    scope: {
      data:"=cardSource",
    },
    restrict: 'E',
    templateUrl: 'app/templates/card-app.html',
    controller: 'AppsCtrl',
    controllerAs: "ac",
    bindToController: true,
    link: function(scope, element, attrs, ctrl) {
        scope.removeCredentials = function() {
            return scope.ac.removeCredentials();
        };
    }
  };
})


.directive('pinRequired', function(Auth) {
  return {   
    restrict: 'A',
    link: function(scope, element, attrs, ctrl) {

      attrs.authorized = false;

      element.on('click', function(e){
        // console.log("\t\t + attrs.authorized:"+attrs.authorized);
        if (attrs.authorized) {
          if (attrs.href) location.href = attrs.href;
          return true;

        } else {


          e.preventDefault();
          e.stopPropagation();

          Auth.askPIN(true)
            .then(function() {
              // console.log("inclusions.js::pinRequired - askPin - AUTHORIZED");
              //THE PIN IS CORRECT!
              attrs.authorized = true;
              element.triggerHandler('click');
              attrs.authorized = false;
            });
        }
      });
    }
  };
})

;

apps.html

<ion-view view-title="Apps">
  <ion-content padding="true" class="has-header bg-stable">


    <h4 class="list-title"><i class="material-icons">&#xE8CA;</i> {{ 'App List' | translate }}

        <!--label class="toggle toggle-calm pull-right toggle-small">
            <span class="toggle-label" translate>My Apps</span>
            <input type="checkbox" ng-model="onlyMyApps">
            <div class="track">
                <div class="handle"></div>
            </div>
        </label-->
    </h4>

    <ion-list class="">
      <card-app     ng-repeat="app in apps | filter:(onlyMyApps || '') && {used: true}"
                    card-source="app"
                    class="{{app.used ? 'used' : 'unused'}}"></card-app>

      <div class="item padding" ng-show="showNoItems"><p class="text-center">{{ 'No saved credentials' | translate}}</span>.</p>
      </div>


    </ion-list>
  </ion-content>
</ion-view>

卡app.html

 <ion-item
              menu-close=""
              class="card item-thumbnail-left item-icon-right app-item">
    <!--<img ng-src="{{data.thumb}}">-->
                <span style="line-height:70px;vertical-align:middle" class="item-image avatar-initials h2">{{data.title|initials}}</span>
                <div class="item">
                    <h2 class="inline-block">
                        <span ng-bind="data.title"></span>
                    </h2>
                    <span class="icon-right material-icons" ng-click='removeCredentials()'>&#xE888;</span>
                    <div>
                        <span>{{'Active helper' | translate}}</span>
                        <h3>{{ data.desc | translate }}</h3>
                    </div>
                </div>
</ion-item>

解决方案:最后没有触发点击事件,因为我的css中必须add pointer-events: auto;cursor: pointer;

1 个答案:

答案 0 :(得分:0)

如果你的指令需要从父控制器调用一个函数,只需将其作为参数传递(就像你尝试过的那样)。

首先确保控制器范围可用于指令。例如,创建简单方法并在指令之前调用它:

// to ensure scope is ok
<button ng-click="alertMethod()"></button>

<card-app ng-repeat='' card-source='' class='' my-method="alertMethod()"></card-app>

// directive
//
scope: {
    myMethod: '&'
},
template: "<button ng-click='myMethod()'>Click</button>"

这应该可行,但如果你的控制器范围不可用,你可能需要使用命名控制器:

https://docs.angularjs.org/api/ng/directive/ngController

  

当多个控制器应用于元素时,使用controller as可以明显地在模板中访问哪个控制器。

比你的代码:

// controller
this.alertMethod = function() {        
    alert('Hello');
}

// view
<div ng-app="myApp" ng-controller="testCtrl as ctrl">
<card-app ng-repeat='' card-source='' class='' my-method="ctrl.alertMethod()"></card-app>