admin管理员组

文章数量:1296491

I'm trying to create a simple blog website using AngularJS. I'm just starting out, so what I'm thinking my not be the best way to do this, so any alternative suggestions are wele.

I have a controller.js file with two blog controllers. One to display a list of blog posts, and the other that displays the post content by including an HTML file.

controller.js

myAppControllers.controller('BlogListCtrl', ['$scope', '$http', function ($scope, $http) {
    $http.get('articles/articles.json').success(function (articles) {
        $scope.articles = articles;
    });
}]);

myAppControllers.controller('BlogPostCtrl', ['$scope', '$routeParams', function ($scope, $routeParams) {
    $scope.includeFile = 'articles/' + $routeParams.blogPostId + '.html';
}]);

articles.json

[
{
    "id": "test-article-one",
    "title": "Test Article one",
    "author": "Gareth Lewis",
    "datePosted": "2015-06-23",
    "summary": "This is a test summary"
},
{
    "id": "test-article-two",
    "title": "Test article two",
    "author": "Gareth Lewis",
    "datePosted": "2015-06-23",
    "summary": "This is a test for article two"
}
]

app.js

when('/blog', {
            templateUrl: 'partials/blog-articles.html',
            controller: 'BlogListCtrl'
        }).
        when('/blog/:blogPostId', {
            templateUrl: 'partials/blog-post.html',
            controller: 'BlogPostCtrl'
        }).

blog-post.html

<ng-include src="'partials/header.html'"></ng-include>

<!-- Want to add title, author, datePosted information here... -->

<article class="content">
    <ng-include src="includeFile"></ng-include>
</article>

This blog listings work fine. When I click into a blog post, it also serves up the content from the HTML file OK as well. However, I want to be able to reuse the title, author and datePosted properties from the selected article in the blog-post.html partial view. What's the best way to do this? Would I need to pass them to the Controller somehow to then pass to the view? I don't really want to pass these as routeParams. Or would I need to do a $http.get on articles.json and iterate through to find the selected article and then pass the property values back to the view?

Thanks for the help.

I'm trying to create a simple blog website using AngularJS. I'm just starting out, so what I'm thinking my not be the best way to do this, so any alternative suggestions are wele.

I have a controller.js file with two blog controllers. One to display a list of blog posts, and the other that displays the post content by including an HTML file.

controller.js

myAppControllers.controller('BlogListCtrl', ['$scope', '$http', function ($scope, $http) {
    $http.get('articles/articles.json').success(function (articles) {
        $scope.articles = articles;
    });
}]);

myAppControllers.controller('BlogPostCtrl', ['$scope', '$routeParams', function ($scope, $routeParams) {
    $scope.includeFile = 'articles/' + $routeParams.blogPostId + '.html';
}]);

articles.json

[
{
    "id": "test-article-one",
    "title": "Test Article one",
    "author": "Gareth Lewis",
    "datePosted": "2015-06-23",
    "summary": "This is a test summary"
},
{
    "id": "test-article-two",
    "title": "Test article two",
    "author": "Gareth Lewis",
    "datePosted": "2015-06-23",
    "summary": "This is a test for article two"
}
]

app.js

when('/blog', {
            templateUrl: 'partials/blog-articles.html',
            controller: 'BlogListCtrl'
        }).
        when('/blog/:blogPostId', {
            templateUrl: 'partials/blog-post.html',
            controller: 'BlogPostCtrl'
        }).

blog-post.html

<ng-include src="'partials/header.html'"></ng-include>

<!-- Want to add title, author, datePosted information here... -->

<article class="content">
    <ng-include src="includeFile"></ng-include>
</article>

This blog listings work fine. When I click into a blog post, it also serves up the content from the HTML file OK as well. However, I want to be able to reuse the title, author and datePosted properties from the selected article in the blog-post.html partial view. What's the best way to do this? Would I need to pass them to the Controller somehow to then pass to the view? I don't really want to pass these as routeParams. Or would I need to do a $http.get on articles.json and iterate through to find the selected article and then pass the property values back to the view?

Thanks for the help.

Share Improve this question edited Jun 26, 2015 at 17:03 Diptendu 2,1581 gold badge17 silver badges30 bronze badges asked Jun 26, 2015 at 16:26 Gareth LewisGareth Lewis 7512 gold badges15 silver badges36 bronze badges 2
  • 3 Your first controller logic should really be a Service instead. docs.angularjs/guide/services – Matthew Green Commented Jun 26, 2015 at 16:30
  • Possible duplicate of Pass variables to AngularJS controller, best practice? – T.Todua Commented Sep 20, 2016 at 11:29
Add a ment  | 

3 Answers 3

Reset to default 3

You said that suggestions are wele, so here it goes.

1 - Transport all your Blog logic to a service;

2 - Provide the data on resolving routes. This is a better approach to handle errors during the load time, 404s, and so on. You can provide a listener to $routeChangeError and deal with it there;

3 - On the service declared below, you have the methods to call your data and a method to retrieve the list cached on the service:

// services.js
myAppServices
    .service('BlogService', ['$http', '$q', function ($http, $q) {
        var api = {},
            currentData = {
                list: [],
                article: {}
            };

        api.getSaved = function () {
            return currentData;
        };

        api.listArticles = function () {
            var deferred = $q.defer(),
                backup = angular.copy(currentData.list);

            $http.get('articles/articles.json')
                .then(function (response) {
                    currentData.list = response;

                    deferred.resolve(response);
                }, function () {
                    currentData.list = backup;

                    deferred.reject(reason);
                });

            return deferred.promise;
        };

        api.getArticle = function (id) {
            var deferred = $q.defer(),
                backup = angular.copy(currentData.article),
                path = 'articles/' + id + '.html';

            $http.get(path, {
                cache: true
            })
                .then(function (response) {
                    currentData.article = {
                        path: path,
                        response: response
                    };

                    deferred.resolve(currentData.article);
                }, function (reason) {
                    currentData.article = backup;

                    deferred.reject(currentData.article);
                });

            return deferred.promise;
        };

        return api;
    }]);

The BlogService.getSaved() will retrieve the stored data, made after each call.

I've made a method to call the ng-include path too, so you can verify if it exists, with cache === true, the browser will keep a copy of it, when calling it again on the view. A copy of the response of the blog article is made too, so you can access its path and the response whenever you need.

On the controllers below, they were adaptated to supply the current needs:

// controller.js
myAppControllers
    .controller('BlogListCtrl', ['$scope', 'articles',
        function ($scope, articles) {
            $scope.articles = articles;

            /* OTHER STUFF HERE */
        }
    ])
    .controller('BlogPostCtrl', ['$routeParams', '$scope', 'article' 'BlogService',
        function ($routeParams, $scope, article, BlogService) {
            // On `article` dependency, you have both the original response
            // and the path formed. If you want to use any of it.

            $scope.includeFile = article.path;

            // To get the current stored data (if any):
            $scope.articles = BlogService.getSaved().list;

            // Traverse the array to get your current article:
            $scope.article = $scope.articles.filter(function (item) {
                return item.id === $routeParams.id;
            });

            /* OTHER STUFF HERE */
        }
    ]);

And the route declarations were changed to load the data when resolving the routes.

// app.js
$routeProvider
    .when('/blog', {
        templateUrl: 'partials/blog-articles.html',
        controller: 'BlogListCtrl',
        resolve: {
            articles: ['BlogService', '$routeParams', function (BlogService, $routeParams) {
                return BlogService.listArticles();
            }]
        }
    })
    .when('/blog/:id', {
        templateUrl: 'partials/blog-post.html',
        controller: 'BlogPostCtrl',
        resolve: {
            article: ['BlogService', '$routeParams', function (BlogService, $routeParams) {
                return BlogService.getArticle($routeParams.blogPostId);
            }]
        }
    })

This is maybe a mon question in angular. What you have to understand is that Scope is defined per controller... In order to share data across controller you still have the option to use $scope.$parent or $rootScope to link controllers but I would use those carefully.

It is better to use Angular Services which are based on singleton patterns therefore you can use them to share information between controllers and I think it will be a better approach.

I found that this has been previously discussed and here are some good examples:

AngularJS Service Passing Data Between Controllers

You can use a global scope to set this data, or you can use service to municate between the controllers. There is a lot of ways to resolve this problem read a little bit more about services in the link bellow and see if you can find how to resolve your problem.

AngularJS: Service vs provider vs factory

本文标签: javascriptAngularJSPass parameters into ControllerStack Overflow