programing

AngularJS: ng-repeat에서 동적으로 컨트롤러 할당

mailnote 2023. 10. 3. 11:15
반응형

AngularJS: ng-repeat에서 동적으로 컨트롤러 할당

다음과 같이 포함된 템플릿에 대해 컨트롤러를 동적으로 할당하려고 합니다.

<section ng-repeat="panel in panels">
    <div ng-include="'path/to/file.html'" ng-controller="{{panel}}"></div>
</section>

는 Angular 는합니다를 한다고 합니다.{{panel}}정의되지 않았습니다.

을.{{panel}}아직 정의되지 않았습니다 (왜냐하면 나는 메아리칠 수 있기 때문입니다){{panel}}템플릿 내부).

를 .ng-controller과 같은 와 같습니다.음:ng-controller="template.ctrlr"는 ., 는, 을 찾을 수 {{panel}}에 입수 ng-controller필요합니다.

도 추신 했습니다를 .ng-controller="{{panel}}"(그때쯤 해결됐을 거라고 생각하는) 내 템플릿에는 있지만 주사위는 없습니다.

당신의 문제는 ng-controller가 단지 컨트롤러 이름으로 문자열을 지정하는 것이 아니라 컨트롤러 자체를 가리켜야 한다는 것입니다.

따라서 $scope을 정의하는 것이 좋습니다.컨트롤러에 대한 포인터가 있는 배열의 사이드 패널은 다음과 같습니다.

$scope.sidepanels = [Alerts, Subscriptions];

다음은 js fiddle http://jsfiddle.net/ADukg/1559/ 에 대한 작업 예시입니다.

그러나 ngRepeat에서 컨트롤러를 설정하고 싶을 때 이 모든 상황이 매우 이상하다고 생각합니다.

템플릿에서 컨트롤러를 동적으로 설정하려면 컨트롤러와 연결된 생성자 함수에 대한 참조를 가질 수 있습니다.컨트롤러의 컨스트럭터 함수는 당신이 전달하는 함수입니다.controller()Angular's module API의 방법

지시문에 전달된 문자열이 등록된 컨트롤러의 이름이 아닌 경우 이를 사용하면 도움이 됩니다.ngController는 문자열을 현재 범위에서 평가할 식으로 취급합니다.이 범위 표현식은 컨트롤러 생성자에게 평가해야 합니다.

예를 들어, Angular가 템플릿에서 다음과 같이 마주친다고 가정합니다.

ng-controller="myController"

:myController되면 Angular입니다를 $scope.myController전류를 포함하는 컨트롤러에 저장합니다.이 키가 스코프에 존재하고 해당 값이 컨트롤러 생성자인 경우 컨트롤러가 사용됩니다.

이는 매개 변수 값에 대한 설명에서 문서에 언급되어 있습니다. "글로벌 액세스가 가능한 생성자 함수의 이름 또는 현재 범위에서 생성자 함수로 평가되는 식을 말합니다."Angular source code의 code comments는 여기에서 이 내용을 더 자세히 설명합니다.

기본적으로 각도는 컨트롤러에 연결된 생성자에 쉽게 액세스하지 않습니다.할 때n를 사용하기 입니다.controller()Angular's module API의 method, 그것은 당신이 그것을 통과시킨 contactor를 private variable에 숨깁니다.여기 $ControllerProvider 소스 코드에서 확인할 수 있습니다.(더controllers입니다에 입니다.$ControllerProvider.)

은 입니다라는 서비스를 입니다.registerController컨트롤러 등록에 사용할 수 있습니다.이 서비스는 컨트롤러 등록 시 컨트롤러와 컨트롤러 컨스트럭터를 모두 노출합니다.이를 통해 컨트롤러를 일반적인 방식과 동적으로 모두 사용할 수 있습니다.

여기 제가 작성한 코드가 있습니다.registerController다음을 수행하는 서비스:

var appServices = angular.module('app.services', []);

// Define a registerController service that creates a new controller
// in the usual way.  In addition, the service registers the
// controller's constructor as a service.  This allows the controller
// to be set dynamically within a template.
appServices.config(['$controllerProvider', '$injector', '$provide',
  function ($controllerProvider, $injector, $provide) {
    $provide.factory('registerController',
      function registerControllerFactory() {
        // Params:
        //   constructor: controller constructor function, optionally
        //     in the annotated array form.
        return function registerController(name, constructor) {
            // Register the controller constructor as a service.
            $provide.factory(name + 'Factory', function () {
                return constructor;
            });
            // Register the controller itself.
            $controllerProvider.register(name, constructor);
        };
    });
}]);

다음은 서비스를 사용하여 컨트롤러를 등록하는 예입니다.

appServices.run(['registerController',
  function (registerController) {

    registerController('testCtrl', ['$scope',
      function testCtrl($scope) {
        $scope.foo = 'bar';
    }]);

}]);

를 합니다라는 합니다.testCtrl를 시킵니다.testCtrlFactory.

이제 일반적인 방식으로 템플릿에서 컨트롤러를 사용할 수 있습니다.

ng-controller="testCtrl"

아니면 역동적으로..

ng-controller="templateController"

후자가 작동하려면 현재 범위에 다음 사항이 있어야 합니다.

$scope.templateController = testCtrlFactory

컨트롤러를 이렇게 정의하기 때문에 이러한 문제가 발생한 것으로 생각됩니다(제가 늘 하던 것처럼).

app.controller('ControllerX', function() {
    // your controller implementation        
});

에 할 수는 ControllerX '이 글로벌 대신 현('Class'면)다됩니다)에됩니다.$controllerProvider).

컨트롤러 참조를 동적으로 할당하거나 수동으로 생성하는 대신 템플릿을 사용하는 것이 좋습니다.

컨트롤러

var app = angular.module('app', []);    
app.controller('Ctrl', function($scope, $controller) {
    $scope.panels = [{template: 'panel1.html'}, {template: 'panel2.html'}];        
});

app.controller("Panel1Ctrl", function($scope) {
    $scope.id = 1;
});
app.controller("Panel2Ctrl", function($scope) {
    $scope.id = 2;
});

템플릿(모의)

<!-- panel1.html -->
<script type="text/ng-template" id="panel1.html">
  <div ng-controller="Panel1Ctrl">
    Content of panel {{id}}
  </div>
</script>

<!-- panel2.html -->
<script type="text/ng-template" id="panel2.html">
  <div ng-controller="Panel2Ctrl">
    Content of panel {{id}}
  </div>
</script>

보다

<div ng-controller="Ctrl">
    <div ng-repeat="panel in panels">
        <div ng-include src="panel.template"></div>        
    </div>
</div>

jsFiddle: http://jsfiddle.net/Xn4H8/

또 다른 방법은 ng-repeat을 사용하지 않고 그것들을 정리하는 지시입니다.

HTML

<mysections></mysections>

지시

angular.module('app.directives', [])
    .directive('mysections', ['$compile', function(compile){
        return {
            restrict: 'E',
            link: function(scope, element, attrs) {
                for(var i=0; i<panels.length; i++) {
                    var template = '<section><div ng-include="path/to/file.html" ng-controller="'+panels[i]+'"></div></section>';
                    var cTemplate = compile(template)(scope);

                    element.append(cTemplate);
                }
            }
        }
    }]);

네, 여기서 가장 간단한 해결책은 컨트롤러를 파일의 템플릿에 명시적으로 정의하는 것입니다.예를 들어 배열을 가지고 있다고 가정해 보겠습니다.

$scope.widgets = [
      {templateUrl: 'templates/widgets/aWidget.html'},
      {templateUrl: 'templates/widgets/bWidget.html'},
];

그러면 html 파일에 다음을(를)

<div ng-repeat="widget in widgets">
    <div ng-include="widget.templateUrl"></div>
</div>

솔루션 aWidget.html:

<div ng-controller="aWidgetCtrl">
   aWidget
</div>

bWidget.html:

<div ng-controller="bWidgetCtrl">
   bWidget
</div>

간단해요!템플릿에 컨트롤러 이름만 정의하면 됩니다.컨트롤러를 bmleite로 정의하면 다음과 같습니다.

app.controller('ControllerX', function() {
// your controller implementation        
});

이게 내가 생각해낼 수 있는 최선의 해결책입니다여기서 유일한 문제는 컨트롤러가 50개 정도인 경우 각 템플릿에 명시적으로 정의해야 하지만 컨트롤러를 수동으로 설정한 상태에서 ng-repeat을 사용하므로 어쨌든 이 작업을 수행해야 했습니다.

언급URL : https://stackoverflow.com/questions/13944207/angularjs-dynamically-assign-controller-from-ng-repeat

반응형