如何获取angular.js将内容加载到模态中

时间:2021-01-13 19:37:58

I need some help making my solution to this problem more elegant.

我需要一些帮助,使我对这个问题的解决方案更加优雅。

Summary of app

应用摘要

The app is a single-page app using pushstate. The landing page (path: /) contains links to articles (path: /article/:articleId). There is also a link to create an article (path: /create). When either link is clicked, the URL is changed and the content is loaded into a modal (I'm using Bootstrap but the implementation is fairly irrelevant).

该应用是使用pushstate的单页应用。登录页面(路径:/)包含文章的链接(路径:/ article /:articleId)。还有一个创建文章的链接(路径:/ create)。单击任一链接时,URL将被更改,内容将加载到模式中(我使用的是Bootstrap但实现方式相当无关紧要)。

Solution

So far I have (and please excuse errors as I'm coding blind):

到目前为止,我有(并请原谅我编码盲目的错误):

index.htm

index.htm的

<!doctype html>
<html ng-app="App">
    <head>
        <title>{{page.title}}</title>
    </head>

    <body>
        <section id="articles" ng-controller="HomepageCtrl">
            <ul>
                <li ng-repeat="article in articles">
                    <a href="/article/{{article.id}}">{{article.name}}</a>
                </li>
            </ul>
        </section>

        <!-- markup simplified for example -->
        <modal id="modal">
            <div class="content ng-view></div>
        </modal>
    </body>
</html>

app.js

app.js

angular.module('Application', [], ['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
    $routeProvider.when('/article/:articleId', {
        templateUrl : '/templates/article.htm',
        controller  : 'ArticleCtrl'
    }).when('/create', {
        templateUrl : '/templates/create.html',
        controller  : 'CreateCtrl'
    });

    $locationProvider.html5Mode(true);
}]).controller('HomepageCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
    $rootScope.page = {
        title : 'This is the homepage'
    };

    $scope.articles = [];
    $scope.articles.push({
        id   : 1,
        name : 'Interesting article'
    });
}]).controller('ArticleCtrl', ['$scope', '$rootScope', '$routeParams', function($scope, $rootScope, $routeParams) {
    $('#modal').modal();

    $rootScope.page = {
        title : 'This is article {{article.name}}' /* Not sure if this works! */
    };
}]).controller('CreateCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
    $('#modal').modal();

    $rootScope.page = {
        title : 'This is the article creation form'
    };
}]);

Templates omitted.

模板省略。

Problem

问题

While this solution works, it's not great. The homepage content remains in the background and is separated from the modal content, which is good. When the route is matched, the template content is retrieved and the controller is hit, the modal opens displaying the content (ng-view). This is also good. However, I don't think controllers should be opening modals.

虽然这个解决方案有效但并不好。主页内容保留在后台并与模态内容分开,这很好。当路线匹配时,检索模板内容并点击控制器,模态打开显示内容(ng-view)。这也很好。但是,我认为控制器不应该打开模态。

What is the most elegant way of doing this? The concept of routing content into the modal with unique controllers is significant to the application: there will be lots more pages added which will all need to follow this convention. There are other caveats, e.g. browser back button and closing the modal should return user to homepage, but these are less significant right now. Once I understand where to sit this logic and how it interfaces with the controllers I'll be happy.

这样做最优雅的方式是什么?使用唯一控制器将内容路由到模态的概念对于应用程序来说非常重要:将添加更多页面,这些页面都需要遵循此约定。还有其他警告,例如浏览器后退按钮和关闭模式应该返回用户到主页,但这些现在不太重要。一旦我理解了这个逻辑的位置以及它与控制器的接口,我会很高兴。

1 个解决方案

#1


2  

I'm going to give this a shot, hopefully the answer will be what you're looking for.

我打算给它一个机会,希望答案将是你正在寻找的。

Any DOM manipulation (as @m.e.conroy said above) should not be done in a controller, but should instead be done in a directive. You can easily communicate between your controller and the directive by doing any number of things. I'm not going to go through an entire example, but this will hopefully get you pointed in the right direction.

任何DOM操作(如上所述@m.e.conroy)都不应该在控制器中完成,而应该在指令中完成。通过执行任何操作,您可以轻松地在控制器和指令之间进行通信。我不打算通过一个完整的例子,但这有望让你指向正确的方向。

To create a "modal" directive, you would do something like the following:

要创建“模态”指令,您可以执行以下操作:

.directive('myModal', [ // declare any dependencies here
    function() {
        return {
            restrict: 'EA',
            templateUrl: 'path/to/the/modal/template.html',
            replace: true,
            scope: { currArticle: '='},  // create a two-way binding for "$scope.currArticle"
            link: function(scope, elem, attrs){
                elem.modal();  // initialize the modal using jQuery
                scope.$on('open-modal-' + attrs.name, function(e, article){
                    scope.currArticle = article;
                    elem.modal('open'); // or whatever call will open the modal
                });
            }
        };
    }
]);

And then your read-article template (located at path/to/the/modal/template.html for this example):

然后是您的阅读文章模板(位于此示例的path / to / modal / template.html):

<modal my-modal name="'read-article'">
    <!-- bind to modal content here -->
    {{currArticle.id}}: {{currArticle.name}}
</modal>

And then your controller:

然后你的控制器:

.controller('HomepageCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
    $rootScope.page = {
        title : 'This is the homepage'
    };
    $scope.articles = [];
    $scope.articles.push({
        id   : 1,
        name : 'Interesting article'
    });
    $scope.displayArticle = function(art){
        $scope.$emit('open-modal-read-article', art);
    };
}]);

And finally, your "home" view:

最后,你的“家”观点:

...
<section id="articles" ng-controller="HomepageCtrl">
    <ul>
        <li ng-repeat="article in articles">
            <a href="" ng-click="displayArticle(article)">{{article.name}}</a>
        </li>
    </ul>
</section>
...

And then you would repeat the above steps for the "create" modal. Hopefully that gives you a place to start from and modify as needed. Let me know if you need more clarification.

然后,您将为“创建”模式重复上述步骤。希望这能为您提供一个起点并根据需要进行修改的地方。如果您需要更多说明,请与我们联系。

#1


2  

I'm going to give this a shot, hopefully the answer will be what you're looking for.

我打算给它一个机会,希望答案将是你正在寻找的。

Any DOM manipulation (as @m.e.conroy said above) should not be done in a controller, but should instead be done in a directive. You can easily communicate between your controller and the directive by doing any number of things. I'm not going to go through an entire example, but this will hopefully get you pointed in the right direction.

任何DOM操作(如上所述@m.e.conroy)都不应该在控制器中完成,而应该在指令中完成。通过执行任何操作,您可以轻松地在控制器和指令之间进行通信。我不打算通过一个完整的例子,但这有望让你指向正确的方向。

To create a "modal" directive, you would do something like the following:

要创建“模态”指令,您可以执行以下操作:

.directive('myModal', [ // declare any dependencies here
    function() {
        return {
            restrict: 'EA',
            templateUrl: 'path/to/the/modal/template.html',
            replace: true,
            scope: { currArticle: '='},  // create a two-way binding for "$scope.currArticle"
            link: function(scope, elem, attrs){
                elem.modal();  // initialize the modal using jQuery
                scope.$on('open-modal-' + attrs.name, function(e, article){
                    scope.currArticle = article;
                    elem.modal('open'); // or whatever call will open the modal
                });
            }
        };
    }
]);

And then your read-article template (located at path/to/the/modal/template.html for this example):

然后是您的阅读文章模板(位于此示例的path / to / modal / template.html):

<modal my-modal name="'read-article'">
    <!-- bind to modal content here -->
    {{currArticle.id}}: {{currArticle.name}}
</modal>

And then your controller:

然后你的控制器:

.controller('HomepageCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
    $rootScope.page = {
        title : 'This is the homepage'
    };
    $scope.articles = [];
    $scope.articles.push({
        id   : 1,
        name : 'Interesting article'
    });
    $scope.displayArticle = function(art){
        $scope.$emit('open-modal-read-article', art);
    };
}]);

And finally, your "home" view:

最后,你的“家”观点:

...
<section id="articles" ng-controller="HomepageCtrl">
    <ul>
        <li ng-repeat="article in articles">
            <a href="" ng-click="displayArticle(article)">{{article.name}}</a>
        </li>
    </ul>
</section>
...

And then you would repeat the above steps for the "create" modal. Hopefully that gives you a place to start from and modify as needed. Let me know if you need more clarification.

然后,您将为“创建”模式重复上述步骤。希望这能为您提供一个起点并根据需要进行修改的地方。如果您需要更多说明,请与我们联系。