Может содержать контроллер загрузки ng-include, содержащийся в файле html в файле & lt; script & gt; теги (или любым другим способом)? [Дубликат]

Предполагая, что у вас есть

  • , установите Build Action на Resource
  • правильно заданный путь, используя URI-PACK-FORMAT

В моем случае он все еще не показывался.

Clean & Rebuild Не просто Build исправил его для меня!

61
задан isherwood 13 March 2015 в 20:30
поделиться

8 ответов

Я нашел возможное решение, где мне не нужно знать о контроллере перед загрузкой:

// Make module Foo and store $controllerProvider in a global
var controllerProvider = null;
angular.module('Foo', [], function($controllerProvider) {
    controllerProvider = $controllerProvider;
});
// Bootstrap Foo
angular.bootstrap($('body'), ['Foo']);

// .. time passes ..

// Load javascript file with Ctrl controller
angular.module('Foo').controller('Ctrl', function($scope, $rootScope) {
    $scope.msg = "It works! rootScope is " + $rootScope.$id +
        ", should be " + $('body').scope().$id;
});
// Load html file with content that uses Ctrl controller
$('<div id="ctrl" ng-controller="Ctrl" ng-bind="msg">').appendTo('body');

// Register Ctrl controller manually
// If you can reference the controller function directly, just run:
// $controllerProvider.register(controllerName, controllerFunction);
// Note: I haven't found a way to get $controllerProvider at this stage
//    so I keep a reference from when I ran my module config
function registerController(moduleName, controllerName) {
    // Here I cannot get the controller function directly so I
    // need to loop through the module's _invokeQueue to get it
    var queue = angular.module(moduleName)._invokeQueue;
    for(var i=0;i<queue.length;i++) {
        var call = queue[i];
        if(call[0] == "$controllerProvider" &&
           call[1] == "register" &&
           call[2][0] == controllerName) {
            controllerProvider.register(controllerName, call[2][1]);
        }
    }
}
registerController("Foo", "Ctrl");
// compile the new element
$('body').injector().invoke(function($compile, $rootScope) {
    $compile($('#ctrl'))($rootScope);
    $rootScope.$apply();
});

Fiddle . Единственная проблема заключается в том, что вам нужно сохранить $controllerProvider и использовать его в том месте, где он действительно не должен использоваться (после загрузки). Также нет простого способа получить функцию, используемую для определения контроллера, пока он не будет зарегистрирован, поэтому мне нужно пройти через модуль _invokeQueue, который недокументирован.

UPDATE : Для регистрации директив и служб вместо $controllerProvider.register просто используйте $compileProvider.directive и $provide.factory соответственно. Опять же, вам нужно сохранить ссылки на них в исходной конфигурации вашего модуля.

UDPATE 2: Вот скрипка , которая автоматически регистрирует все контроллеры / директивы / службы, загруженные без необходимости укажите их индивидуально.

69
ответ дан Jussi Kosunen 22 August 2018 в 16:52
поделиться
  • 1
    Скрипка в UPDATE 2 была идеальной, именно то, что мне нужно. – Tyson 17 September 2013 в 08:04
  • 2
    Хм ... это дает мне ошибку при попытке вызвать функцию .injector(), называя ее неопределенной. Я использую angular1.2.23. Устарела ли она в новых версиях? – Aarmora 8 January 2015 в 03:02
  • 3
    это тоже дает мне ошибку! [Ошибка: [ng: areq] errors.angularjs.org/1.2.26/ng/… – Ali Adlavaran 21 April 2015 в 10:21
  • 4
    Работает для меня в 1.3.15. Если вы можете воспроизвести его в jsfiddle / plunker, тогда я мог бы посмотреть на это, в противном случае это немного сложно диагностировать. – Jussi Kosunen 21 April 2015 в 12:51
  • 5
    и как насчет фильтров? – devmao 28 April 2015 в 15:00

Мне также нужно было добавить несколько представлений и связать их с контроллерами во время выполнения из javascript-функции вне контекста angularJs, поэтому вот что я придумал:

<div id="mController" ng-controller="mainController">
</div>

<div id="ee">
  2nd controller's view should be rendred here
</div>

теперь вызывает функцию setCnt () будет вводить и компилировать html, и он будет связан со вторым контроллером:

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

function setCnt() {
  // Injecting the view's html
  var e1 = angular.element(document.getElementById("ee"));
  e1.html('<div ng-controller="ctl2">my name: {{name}}</div>');

  // Compile controller 2 html
  var mController = angular.element(document.getElementById("mController"));
  mController.scope().activateView(e1);
}

app.controller("mainController", function($scope, $compile) {
  $scope.name = "this is name 1";

  $scope.activateView = function(ele) {
    $compile(ele.contents())($scope);
    $scope.$apply();
  };
});

app.controller("ctl2", function($scope) {
  $scope.name = "this is name 2";
});

вот пример, чтобы проверить это: http://refork.com/x4bc

надеюсь, что это поможет.

2
ответ дан Chtiwi Malek 22 August 2018 в 16:52
поделиться
  • 1
    Я использовал ваш подход для динамического добавления контроллера. Я хочу добавить javascript-объект к этому контроллеру. Не могли бы вы мне помочь. Я задал вопрос о stackoverflow stackoverflow.com/questions/36597885/… – Kaustubh Khare 14 April 2016 в 06:20
  • 2
    да, вы можете использовать RequireJS для загрузки вашего javascript и получить свой объем контроллера, как я сделал в моем примере mController.scope() – Chtiwi Malek 14 April 2016 в 10:26
  • 3
    может у, пожалуйста, объясните мне подробно, используя мой вопрос. Я мало знаю о требованиях. – Kaustubh Khare 14 April 2016 в 10:41
'use strict';

var mainApp = angular.module('mainApp', [
    'ui.router', 
    'ui.bootstrap', 
    'ui.grid',
    'ui.grid.edit',
    'ngAnimate',
    'headerModule', 
    'galleryModule', 
    'appointmentsModule', 
 ]);


(function(){

    var App = {
        setControllers:   mainApp.controller(controllers),
        config:   config.config(),
        factories: {
            authFactory: factories.auth(),
            signupFactory: factories.signup(),
            someRequestFactory: factories.saveSomeRequest(),
        },
        controllers: {
            LoginController: controllers.userLogin(),
            SignupController: controllers.signup(),
            WhateverController: controllers.doWhatever(),
        },
        directives: {
            signup: directives.signup(), // add new user
            openLogin: directives.openLogin(), // opens login window
            closeModal: directives.modalClose(), // close modal window
            ngFileSelect: directives.fileSelect(),
            ngFileDropAvailable: directives.fileDropAvailable(),
            ngFileDrop: directives.fileDrop()
        },
        services: {
           $upload: services.uploadFiles(),
        }
    };
})();

Приведенный выше код является только примером.

Таким образом, вам не нужно помещать ng-controller="someController" в любом месте страницы - вы только объявляете <body ng-app="mainApp">

Такая же структура может использоваться для каждого модуля или модулей внутри модулей

0
ответ дан Community 22 August 2018 в 16:52
поделиться

Я только что улучшил функцию, написанную Jussi-Kosunen, так что все вещи могут быть выполнены с помощью одного вызова.

function registerController(moduleName, controllerName, template, container) {
    // Load html file with content that uses Ctrl controller
    $(template).appendTo(container);
    // Here I cannot get the controller function directly so I
    // need to loop through the module's _invokeQueue to get it
    var queue = angular.module(moduleName)._invokeQueue;
    for(var i=0;i<queue.length;i++) {
        var call = queue[i];
        if(call[0] == "$controllerProvider" &&
            call[1] == "register" &&
            call[2][0] == controllerName) {
                controllerProvider.register(controllerName, call[2][1]);
            }
        }

        angular.injector(['ng', 'Foo']).invoke(function($compile, $rootScope) {
            $compile($('#ctrl'+controllerName))($rootScope);
            $rootScope.$apply();
        });
}

Таким образом вы можете программно загрузить ваш шаблон из любого места и инстанцировать контроллеры, даже вложенные.

Вот рабочий пример загрузки контроллера внутри другого: http://plnkr.co/edit/x3G38bi7iqtXKSDE09pN

1
ответ дан David Vartanian 22 August 2018 в 16:52
поделиться
  • 1
    Собственно, после обучения больше Углового, я думаю, что все это концептуально (или технически) неправильно. Используя директивы, вы можете сделать то же самое, но намного проще. – David Vartanian 5 March 2015 в 02:20

почему бы не использовать config и ui-router?

он загружается во время выполнения, и вам не нужно показывать свои контроллеры в html-коде

, например, что-то вроде следующего

var config = {

   config: function(){
        mainApp.config(function ($stateProvider, $urlRouterProvider){
            $urlRouterProvider.otherwise("/");
            $stateProvider

            .state('index',{
                views:{
                    'main':{
                        controller: 'PublicController',
                        templateUrl: 'templates/public-index.html'
                    }
                }
            })
            .state('public',{
                url: '/',
                parent: 'index',
                views: {
                    'logo' : {templateUrl:'modules/header/views/logo.html'},
                    'title':{
                        controller: 'HeaderController',
                        templateUrl: 'modules/header/views/title.html'
                    },
                    'topmenu': {
                        controller: 'TopMenuController',
                        templateUrl: 'modules/header/views/topmenu.html'
                    },
                    'apartments': {
                        controller: 'FreeAptController',
                        templateUrl:'modules/free_apt/views/apartments.html'
                    },
                    'appointments': {
                        controller: 'AppointmentsController',
              templateUrl:'modules/appointments/views/frm_appointments.html'
                    },
                }
            })
            .state('inside',{
                views:{
                    'main':{
                        controller: 'InsideController',
                        templateUrl: 'templates/inside-index.html'
                    },
                },
                resolve: {
                    factory:checkRouting
                }
            })
            .state('logged', {
                url:'/inside',
                parent: 'inside',
                views:{        
                    'logo': {templateUrl: 'modules/inside/views/logo.html'},
                    'title':{templateUrl:'modules/inside/views/title.html'},
                    'topmenu': {
                       // controller: 'InsideTopMenuController',
                        templateUrl: 'modules/inside/views/topmenu.html'
                    },
                    'messages': {
                        controller: 'MessagesController',
                        templateUrl: 'modules/inside/modules/messages/views/initial-view-messages.html'
                    },
                    'requests': {
                        //controller: 'RequestsController',
                        //templateUrl: 'modules/inside/modules/requests/views/initial-view-requests.html'
                    },

                }

            })

    });
},

};
1
ответ дан Leonid Auslender 22 August 2018 в 16:52
поделиться
  • 1
    Потому что он не отвечает на вопрос. Он спрашивает, как динамически (ленивая загрузка) контроллеров. Нет, если они видны из HTML или в другом месте. – Jeach 4 March 2018 в 21:04

Предлагаю взглянуть на библиотеку ocLazyLoad , которая регистрирует модули (или контроллеры, службы и т. д. на существующем модуле) во время выполнения, а также загружает их с помощью requireJs или другой такой библиотеки.

7
ответ дан Marius Balčytis 22 August 2018 в 16:52
поделиться
  • 1
    О, мой Bajezus ... это именно то, что все в этом вопросе ищут ... +1 для внимания здесь ... ocLazyLoad - это все и мешок с микрочипами. – Nick Steele 3 December 2015 в 19:32
  • 2
    Я тоже использую это: D иногда вы хотите, чтобы некоторые библиотеки были ленивы загружены по порядку. Поскольку они зависят от других библиотек (которые должны быть загружены в первую очередь). Поэтому я создал синхронный загрузчик, чтобы делать подобные вещи. дайте мне знать, если кто-то захочет, чтобы я написал этого загрузчика. поскольку это может не иметь отношения к этой теме. – r4ccoon 20 May 2016 в 20:11

bootstrap () вызовет для вас компилятор AngularJS, как и ng-app.

// Make module Foo
angular.module('Foo', []);
// Make controller Ctrl in module Foo
angular.module('Foo').controller('Ctrl', function($scope) { 
    $scope.name = 'DeathCarrot' });
// Load an element that uses controller Ctrl
$('<div ng-controller="Ctrl">{{name}}</div>').appendTo('body');
// Bootstrap with Foo
angular.bootstrap($('body'), ['Foo']);

Fiddle .

17
ответ дан Mark Rajcok 22 August 2018 в 16:52
поделиться
  • 1
    Проблема в том, что мне нужно иметь возможность добавлять контроллеры по мере необходимости, было бы невозможно добавить их все в начале, так как их много. Я попытался вызывать бутстрап несколько раз, но также нарушает существующие области (между прочим). – Jussi Kosunen 7 March 2013 в 08:49
  • 2
    @DeathCarrot, я не знаю, как динамически добавлять дополнительные контроллеры. Это может помочь: github.com/matys84pl/angularjs-requirejs-lazy-controllers – Mark Rajcok 7 March 2013 в 23:09
  • 3
    Похоже, вам все равно нужно знать о доступных контроллерах перед загрузкой (routes.js). Тем не менее, перечисление их лучше, чем загрузка их. Спасибо, я, вероятно, в конечном итоге сделаю что-то вроде этого, если я не смогу найти способ сделать это полностью динамически. – Jussi Kosunen 8 March 2013 в 09:22
  • 4
    @Mark Rajcok как передать DeathCarrot в контроллер вместо жестко закодированного значения внутри контроллера? – Dis Shishkov 11 December 2013 в 15:15
  • 5
    Спасибо, Марк, это именно то, что я искал – Anoop Isaac 8 January 2014 в 07:16

Это то, что я сделал, на самом деле 2 части, используя ng-контроллер с его определенной функцией, а затем $ controller service для создания динамического контроллера: -

Во-первых, HTML - нам нужен Static Контроллер, который будет создавать динамический контроллер ..

<div ng-controller='staticCtrl'>
  <div ng-controller='dynamicCtrl'>
    {{ dynamicStuff }}
  </div>
</div>

Статический контроллер «staticCtrl» определяет элемент области с названием «dynamicCtrl», который вызывается для создания динамического контроллера. ng-controller принимает либо предопределенный контроллер по имени, либо просматривает текущую область действия для функции с тем же именем.

.controller('staticCtrl', ['$scope', '$controller', function($scope, $controller) {
  $scope.dynamicCtrl = function() {
    var fn = eval('(function ($scope, $rootScope) { alert("I am dynamic, my $scope.$id = " + $scope.$id + ", $rootScope.$id = " + $rootScope.$id); })');
    return $controller(fn, { $scope: $scope.$new() }).constructor;
  }
}])

Мы используем eval (), чтобы взять строку (наш динамический код, который может исходить из в любом месте), а затем службу $ controller, которая примет либо предопределенное имя контроллера (нормальный случай), либо конструктор функции, за которым следуют параметры конструктора (мы передаем новую область). Угловая впрыснет (как любой контроллер) в функцию, мы запрашивают только $ scope и $ rootScope выше.

0
ответ дан steve 22 August 2018 в 16:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: