无法使用控制器作为语法来设置指令(范围不匹配)

Unable to use controller as syntax to set up directive (scope mismatch)

我正在努力尝试让一个名为 webix-ui 的指令假设与父范围具有相同的范围级别。此代码最接近于使 webix-ui 工作,但该元素仍然看到 childscope。

我哪里做错了,为什么我的控制器没有被全球接收?

我快要放弃了,因为我已经尝试了将近 10-15 种代码变体,这个是最有前途的,希望方向正确。

我可以根据需要提供更多详细信息。

模块控制器

angular.module('Risk').controller('CreateRiskController', ['$http', '$resource', '$scope', '$state', '$window', '$timeout', '$interval', '$sce', 'CommonService', function($http, $resource, $scope, $state, $window, $timeout, $interval, $sce, CommonService){
    refresh = false;
    var vm = this;
    vm.config = {}
    vm.initDone = false;
    vm.setup = {
        done: false
    }
    vm.model = { elem: true }

    vm.risk = {
        risktitle: '',
        riskstatement: '',
        context: '',
        closurecriteria: '',
        likelihood:'',
        technical:'',
        schedule:'',
        cost:''
     }; 

    vm.fields = [   
        'risktitle',
        'riskstatement',
        'context',
        'closurecriteria',
        'likelihood',
        'technical',
        'schedule',
        'cost'
    ]

    vm.risklevels = {
        riskmaximum: '',
        riskhigh: '',
        riskmedium: '',
        riskminimum: ''
    }

    vm.flags = {
        disabled: true
    }

    vm.riskMatrix = [];
    for(var l = 1; l <= 5; l++)
    {
        vm.riskMatrix[l] = [];
        for (var c = 0; c <= 5; c++)
        {
            vm.riskMatrix[l][c] = '';  
        }
    }

    vm.riskLevel = function(l, c){
        elem = document.querySelector("div[name='risk["+l+"]["+c+"]']");
        risk = vm.riskMatrix[l][c];
        if (risk == '')
            return (elem && elem.hasAttribute('class'))?
                    elem.getAttribute('class') : ''; 

        if (risk >= vm.risklevels.riskhigh) 
            return 'cell high';
        else if (risk >= vm.risklevels.riskmedium && risk < vm.risklevels.riskhigh)
            return 'cell med';
        else if (risk < vm.risklevels.riskmedium)
            return 'cell low';
    }


    vm.valid = function(){          
        return CommonService.riskFormValid(vm.fields, vm);
    }

    vm.invalidLevel = function(lvl){
        return CommonService.invalidLevel(lvl);
    }

    $scope.$on("$destroy", function(){
         formcheck = 0;
         angular.element(document.querySelector('link[href="/app/tool/risk/CreateRisk.css"]')).remove();   
    });

    vm.initRisk = function(data){
        vm.risklevels.riskmaximum = data.Levels[0].riskmaximum;
        vm.risklevels.riskhigh = data.Levels[0].riskhigh;
        vm.risklevels.riskmedium = data.Levels[0].riskmedium;
        vm.risklevels.riskminimum = data.Levels[0].riskminimum; 


        for (var idx = 0; idx < data.Thresholds.length; idx++)
        {
            var l = data.Thresholds[idx].likelihood;
            var c = data.Thresholds[idx].consequence;
            v = data.Thresholds[idx].level;
            vm.riskMatrix[l][c] = v;
        }
    }

    vm.init = function(){      
          return $http.get('/api/riskconfig').then(function(response){
               if (response.data.Succeeded){
                    vm.initRisk(response.data.Result);
                    return response.data.Result;
               }
               else{
                    vm.msg = $sce.trustAsHtml(response.data);
               }
          });
    } 

    vm.submit = function(){
        if (!vm.valid())
             vm.msg = "Please complete form and resubmit";
        else{ 
            //vm.actionitem.duedate = vm.split(vm.actionitem.duedate,'T')[0];
            //vm.actionitem.ecd = vm.split(vm.actionitem.ecd, 'T')[0];
            $http.post('/api/risks', vm.risk).then(function(response){
                if (response.data.Succeeded){
                    vm.msg = response.data.Result;
                }
                else{
                    vm.msg = $sce.trustAsHtml(response.data);
                }
            });
        } 
    }
}]);

指令

angular.module('Risk').directive('config', ConfigElement);

function ConfigElement(){
      var directive = {
            restrict: 'A',
            compile: function (){
                return {
                    pre: function (scope, elem, attrs){
                        var vm = scope.vm;
                        vm.config[attrs.config] = {done: false} 
                    },
                    post: ConfigController
                }
            },
            controller: 'CreateRiskController',
            controllerAs: 'vm',
            bindToController: true,
            scope: false
      }
      return directive;     
}                    

function ConfigController(scope, element, attrs, DOMops, ValidationService){
   //$scope.$watch('setup.done', function(dataReady,dataNotReady,scope){
   //    if (dataReady){
            var vm = scope.vm;

            var attr = attrs.config;
            var type = attrs.type;
            var width = attrs.width;
            var height = attrs.height;
            var maxlength = attrs.hasOwnProperty('maxlength')? attrs.maxlength: null;  

            var view;
            if (type == "level")
                view = "text";
            else
                view = type;

            var config = 
            {
                view: view,
                value: vm.risk[attr],      
                on: {
                    "onTimedKeyPress": function(code){  
                        var obj = this.eventSource || this; 
                        ValidationService.handleKeyPress(obj, code, attr);
                        if (type == "level")
                            DOMops.assignRiskLevel(scope, obj); 
                    },
                    "onBlur": function(code){  
                        var obj = this.eventSource || this;  
                        ValidationService.updateAndValidate(obj,code,attr); 
                    }
                },
                responsive: true,
                width: width,
                height: height
            };
            if (maxlength)
                config.attributes = {maxlength : maxlength};
            config.done = true;
            vm.config[attr] = config;
            //$scope.$eval($attrs.onConfig, {$config: $scope.config[$attrs.name]});                    
     // }
   //});  
}  

模板

   <div id="formcontainer" ng-app="Risk" ng-controller="CreateRiskController as vm" get-risk>
        <div id="mycreateform" class="container" type="space" layout-padding="" ng-cloak="">     
            <form id="form" name="CreateRisk" role="form" ng-submit="vm.valid() && vm.submit()" novalidate>
                <div id="details" class="layout" border="1">                               
                    <div class="tr">
                        <div class="td label">
                            Title
                        </div>
                        <div config="risktitle" class="td locked" width="500" height="30" type="text">
                            <div ng-if="vm.config.risktitle.done" ng-model="vm.config.risktitle" webix-ui="vm.config.risktitle" id="risktitle" name="risktitle"></div>
                        </div>
                    </div>
                    <div class="tr">    
                        <div class="td label">
                            Risk Statement
                        </div>
                        <div config="riskstatement" class="td locked" width="500" height="97" type="textarea">
                            <div ng-if="vm.config.riskstatement.done" ng-model="vm.config.riskstatement" webix-ui="vm.config.riskstatement"  id="riskstatement" name="riskstatement"></div>
                        </div>
                    </div>
                    <div class="tr">
                        <div class="td label">
                            Context
                        </div>
                        <div config="context" width="500" height="97" type="textarea" class="td locked">
                            <div ng-if="vm.conig.context.done"  ng-model="vm.config.context" webix-ui="vm.config.context" id="context" name="context"></div>
                        </div>
                    </div>
                    <div class="tr">
                        <div class="td label">
                            Closure Criteria
                        </div>
                        <div config="closurecriteria" width="500" height="97" type="textarea" class="td locked">
                            <div ng-if="vm.config.closurecriteria.done"  ng-model="vm.config.closurecriteria" webix-ui="vm.config.closurecriteria" id="closurecriteria" name="closurecriteria"></div>
                        </div>
                    </div>
                     <!--tr class="text">
                            <div class="td label">
                                Category
                            </div>
                            <div class="locked">
                                 <div id="category" name="category" />
                            </div>
                      </div-->
                </table>
                <h2>Initial Risk Assessment</h2>
                <div class="nested">
                    <div class="info">
                        <div id="details" class="table" border="1">
                            <div class="tr">
                                <div class="td label">
                                    Likelihood
                                </div>
                                <div config="likelihood" width="30" height="30" maxlength="1" type="level" class="td locked">                   
                                    {{config.likelihood}}<div ng-if="vm.config.likelihood.done" ng-model="vm.config.likelihood" webix-ui="vm.config.likelihood" id="likelihood" name="likelihood"></div>
                                </div>
                            </div>
                            <div class="tr">
                                <div class="td label" colspan="2">
                                    Consequence
                                </div>
                            </div>
                             <div class="tr">
                                <div class="td label margin-left">
                                    Technical
                                </div>
                                <div config="technical" width="30" height="30" type="level" maxlength="1" class="td locked">
                                    {{config.technical}}<div ng-if="vm.config.technical.done" ng-model="vm.config.technical" webix-ui="vm.config.technical" id="technical" name="technical"></div>
                                </div>                                                        
                            </div>
                             <div class="tr">
                                <div class="td label margin-left">
                                    Schedule
                                </div>
                                <div config="schedule" width="30" height="30" type="level" maxlength="1" class="td locked">
                                    {{config.schedule}}<div ng-if="vm.config.webix" ng-model="vm.config.schedule" webix-ui="vm.config.schedule"  id="schedule" name="schedule"></div>
                                </div>
                            </div>
                             <div class="tr">
                                <div class="td label margin-left">
                                    Cost
                                </div>
                                <div config="cost" width="30" height="30" type="level" maxlength="1" class="td locked">
                                    {{config.cost}}<div ng-if="vm.config.cost.done"  ng-model="vm.config.cost" webix-ui="vm.config.cost" id="cost" name="cost"></div>
                                </div>
                            </div>
                        </div>
                         <div name="level"></div>
                    </div> 
                    &nbsp;&nbsp;    
                    <div class="info" ng-if="vm.setup.done">
                        <table class="matrix" id="riskmatrix">
                        <tbody>
                        <tr ng-repeat="likelihood in [5,4,3,2,1]">
                                <td ng-if="likelihood == 2" class="vlabel">Likelihood</td>
                                <td ng-if="likelihood != 2"></td>
                                <td class="likelihood">{{likelihood}}</td>
                                <td ng-repeat="consequence in [1,2,3,4,5]" name="risk[{{likelihood}}][{{consequence}}]" ng-model="vm.riskMatrix[likelihood][consequence]" ng-class="[vm.riskLevel(likelihood,consequence)]"></td>
                        </tr>
                        <tr>
                                <td></td>
                                <td></td>
                                <td ng-repeat="consequence in [1,2,3,4,5]">{{consequence}}</td>
                        </tr>
                        <tr>
                            <td></td><td></td><td colspan="5">Consequence</td> 
                        </tr>  
                        </tbody></table>
                    </div>
                     &nbsp;&nbsp;   
                </div>
            <divider></divider>
            <div class="tr">
                <div class="tr">
                  <button id="submit" type="submit" disabled="disabled" class="raised primary">Create Risk</button>
                </div>
            </div>
            <div class="tr">
              <div class="msg" layout-align="center">
                <span ng-bind-html="msg">{{msg}}</span>
              </div>
            </div>
            </form>
        </div>
    </div>

用一个 属性 最初为 false 的对象初始化我的 div 指令,然后在我的模板中使用 "as ctrl" 最终解决了这个问题。我不得不在我的控制器中使用 this,在控制器中使用 scope.ctrl.<property>。它的工作原理似乎与语法相似,因为许多参考文献都建议使用 this 指针而不是 $scope。 我唯一改变的是使用 ng-show 而不是 ng-if。我没有用过 ng-if 但我怀疑它可能仍然有效。

<div id="formcontainer" ng-app="Risk" ng-controller="CreateRiskController as ctrl" ng-cloak>
    <get-risk></get-risk>
    <div id="mycreateform" class="container" type="space" layout-padding="">     
        <form id="form" name="CreateRisk" role="form" ng-submit="ctrl.valid() && ctrl.submit()" novalidate>
            <table id="details" class="layout" border="1">
                <tr>
                    <td class="label">
                        Title
                    </td>
                    <td class="locked">
                        <div ng-show="ctrl.config.risktitle.done" config="risktitle" webix-ui="risktitle" width="500" height="30" type="text" id="risktitle" name="risktitle"></div>
                    </td>
                </tr>
             </table>
        </form>
    </div>
</div>

指令

angular.module('Risk').directive('config', ConfigElement);

function ConfigElement(){
      var directive = {
            restrict: 'A',
            link: linkFn,
            controller: ConfigController
      }

      function linkFn(scope, elem, attrs){
            var attr = attrs.config;
            var type = attrs.type;
            var width = attrs.width;
            var height = attrs.height;
            var maxlength = attrs.hasOwnProperty('maxlength')? attrs.maxlength: null;  

            var view;
            if (type == "level")
                view = "text";
            else
                view = type;

            scope.ctrl.DOMops.setValidationServiceObj(scope.ctrl.ValidationService);
            scope.ctrl.DOMops.setValue('risk', scope.ctrl.risk);
            scope.ctrl.DOMops.setValue('riskMatrix', scope.ctrl.riskMatrix);   
            scope.ctrl.DOMops.setValue('risklevels', scope.ctrl.risklevels);

            scope.ctrl.ValidationService.setValue('risk', scope.ctrl.risk);
            scope.ctrl.ValidationService.setDOMobj(scope.ctrl.DOMops);

            var config = 
            {
                view: view,
                value: scope.ctrl.risk[attr],      
                on: {
                    "onTimedKeyPress": function(){  
                        var obj = this.eventSource || this; 
                        code = this.getValue();
                        scope.ctrl.ValidationService.handleKeyPress(code, scope.ctrl, obj, attr);
                        if (type == "level")
                            scope.ctrl.DOMops.assignRiskLevel(obj); 
                    },
                    "onBlur": function(){  
                        var obj = this.eventSource || this;  
                        code = this.getValue();
                        scope.ctrl.ValidationService.getTextValueAndValidate(code, scope.ctrl, obj, attr); 
                    }
                },
                responsive: true,
                width: width,
                height: height
            };
            if (maxlength)
                config.attributes = {maxlength : maxlength};
            config.done = true;
            scope.ctrl.config[attr] = config;
      }

      return directive;     
}


function ConfigController($scope, $element, $attrs){
    $scope.ctrl.config[$attrs.config] = {done: false};
}