Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bo Jacobsen 593 posts 2389 karma points
    Sep 10, 2017 @ 12:09
    Bo Jacobsen
    0

    Angular powered frontend

    Hi all.

    using umbraco version 7.6.6

    Since i begin to be familar with the angular in the backend. I though it was time to play with some frontend angular.

    I found this article https://24days.in/umbraco-cms/2014/angular-powered-frontend but it's from 2014 and i was thinking that there must be a smarter way in 2017?

    What really confuses me is the angular routing and where to put the templates? And then i would like the preview to work aswell.

    I hope there is some frontend developers who can help or share link :)

  • Ayo Adesina 430 posts 1023 karma points
    Sep 10, 2017 @ 13:30
    Ayo Adesina
    0

    Recently I was given a SPA built in Angular, all the content in the site was arranged in static JSON files.

    So the client wanted the static json files to be genrated by umbraco based on the content in the CMS.

    I'll just out line my approach here maybe it will give you a starting point.

    The Angualar SPA would request a URL like:

    domainName.com/en/news.json
    

    I then used an URL re-write rule to change that URL in to something like

    domainName.com/news?culture=en-Gb
    

    rule goes in the web.config file:

        <rule name="EN-News" stopProcessing="true">
          <match url="^data/en/news.json" ignoreCase="true" />
          <action type="Redirect" url="news?culture=en-gb" />
        </rule>
    

    That then maps to a news node with news items as children the code in the root news node would return the correct json to power the front end application.

    Don't think that is a direct answer to your question, but hope that helps. Ayo

  • Bo Jacobsen 593 posts 2389 karma points
    Sep 11, 2017 @ 07:52
    Bo Jacobsen
    0

    Hi Ayo.

    Thanks for answering.

    Do you then make another rewrite rule for news?culture=en-gb or is the news node in the root folder?

    Atm i am mixing cshtml with angular, just to get started. I am still confused on how to do the SPA.

  • Ayo Adesina 430 posts 1023 karma points
    Sep 11, 2017 @ 09:06
    Ayo Adesina
    0

    Yes I created several rewrite rules.

    I'm not a massive Angular expert but if you have a SPA that needs data in JSON you need to make umbraco respond to the URLs that the SPA expects to recive this data.

    I had something like this in the content tree.

    HomePage << SPA Angualr app lives here (Domain.com)
      -News   << SPA looks for data on domain.com/News 
            -News Item
            -News Item
       -Events SPA looks for data on domain.com/Events 
            - Event Item
            - Event Item
    

    This is just something I thought up... there may be other ways to do this, but thats pretty much what my solution looked like. So depending on the shape of the JSON you want to return you can arrange all you doc types accordingly.

  • Bo Jacobsen 593 posts 2389 karma points
    Sep 16, 2017 @ 22:02
    Bo Jacobsen
    100

    Okay i figured it out.

    I dunno if this is the professional way, but it works exactly as i want it too.

    I try to explain, with as clean code as possible. So it might help others in the future. I'll still like people to commet if they know a better solution.

    All the umbraco documents that i want to use in the SPA, i'll use the same cshtml template on. So i can use the strong mvc structure to load the page on a refresh. On the documents i set 2 properties. One with the path to the htm or html file for the scope. And one with the name of the controller used for the scope. On the cshtml template i set a div with ng-view, that loads the htm or html pages into it. Remember to set the web.config umbracoReservedPaths.

    I try to demostrate.

    web.config

    <!-- Web.config / appSettings -->
    <add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/Scripts,~/Content,~/Pages" /
    

    @Scripts.Render("~/Scripts/js")

    <!-- Scripts.Render("~/Scripts/js") -->
    <script src="~/Scripts/angular.min.js"></script>
    <script src="~/Scripts/angular-route.min.js"></script>
    <script src="~/Scripts/angular-sanitize.min.js"></script>
    <script src="~/Scripts/angular-animate.min.js"></script>
    <script>
        var app = angular.module("app", ['ngRoute', 'ngAnimate', 'ngSanitize']);
        app.controller('mainController', function ($scope) {
            $scope.message = 'I am home!';
        });
        app.controller('subController', function ($scope) {
            $scope.message = 'I am sub!';
        });
    </script>
    

    htm or html, at ~/Pages/...

    <!-- home.html -->
    <p>{{message}}</p>
    
    <!-- sub.html -->
    <p>{{message}}</p>
    

    layout.cshtml

    <!-- Layout.cshtml -->
    @using System.Web.Optimization
    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    
    <html lang="en" ng-app="app">
    <head>
        <!-- base is for Angular Routing so it removes the # and make a pretty url. -->
        <base href="/">
    
        <title>My App</title>
    
        <!-- Render all css here with System.Web.Optimization -->
        @Styles.Render("~/Content/css")
    </head>
    <body>
    
        <!-- Fake menu. This should be rendered from umbraco. -->
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="subpage">Sub</a></li>
            <li><a href="subpage/subpage">Sub 1</a></li>
            <li><a href="subpage/subpage/subpage">Sub 2</a></li>
        </ul>
    
        <!-- Here the views will be loaded into-->
        <div ng-view></div>
    
        <!-- Render all Angular here with System.Web.Optimization -->
        @Scripts.Render("~/Scripts/js")
    
        <!-- Angular routing / This i would manipulate with razor -->
        <script type="text/javascript">
            app.config(function ($routeProvider, $locationProvider) {
                $routeProvider
                // route for the root node
                .when('/', {
                    templateUrl: '/Pages/home.html',
                    controller: 'mainController'
                })
                // route for Sub
                .when('/subpage', {
                    templateUrl: '/Pages/sub.html',
                    controller: 'subController'
                })
                // route for Sub
                .when('/subpage/subpage', {
                    templateUrl: '/Pages/sub.html',
                    controller: 'subController'
                })
                // route for Sub
                .when('/subpage/subpage/subpage', {
                    templateUrl: '/Pages/sub.html',
                    controller: 'subController'
                });
    
                // This beautify the url. But remember to set the base in head.
                $locationProvider.html5Mode(true);
            });
        </script>
    </body>
    </html>
    

    To make the routeconfig dynamic i create a route object in c# and set all the pages from the whole site that has the properties of template and controller to this route object and return it as a list.

    Route entity

    // Route Entity
    public class Route
    {
        public string Url { get; set; }
        public string Template { get; set; }
        public string Controller { get; set; }
    }
    

    Dynamic route config with razor

    <!-- Dynamic route config with razor.-->
    <script>
        app.config(function ($routeProvider, $locationProvider) {@{<text>$routeProvider</text>}@foreach(var route in routes) {<text>.when('@route.Url', { templateUrl: '@route.Template', controller: '@route.Controller' })</text>}; $locationProvider.html5Mode(true); });
    </script>
    
Please Sign in or register to post replies

Write your reply to:

Draft