Code Camper Jump-Start SPA Now Open Source | John Papa

John Papa

Evangelist on the loose

Code Camper Jump-Start SPA Now Open Source

...

I’m proud to announce that the Code Camper Jump-Start SPA with Durandal, Knockout, Breeze and Toastr is now open sourced on GitHub!

If you enjoyed my Single Page Application Jump-Start course, you will be happy to learn that the source code for the final SPA Jump-Start solution is now available! The great folks at Pluralsight worked with me to host the final solution of Code Camper Jump-Start (CCJS) on GitHub. You can grab the code, fork it, make pull requests, or just browse!

spajs

My SPA Jump-Start course helps you walk through and build CCJS step by step. The step by step code is exclusively available to Pluralsight Plus subscribers and the final source is now hosted in this GitHub repository.

I hope you enjoy the code and thank you for watching my courses!

tags: open source pluralsight SPA
  • Samuel

    Thanks for sharing with community…

    Smiles….

  • Hisham Bin Ateya

    Thanks so much SPA geek ..

  • Samuel

    Hi John,
    I’m following this concept SPA few days ago ..
    But now I’m trying to use local data and route do not work! [if (! forceRemote) ... back Q.resolve]

    you can shoot a clue?

    P.S: what is for createNullos?
    when i put my model in there, a toastr.error appears..
    [ //createNullo(entityNames.cv);]

  • Dudley

    I am a longtime .NET developer but not for web applications. The SPA Jumpstart course on Pluralsight is superb. From never having written javascript before, I am now almost ready to create rich client web applications.

    One problem I had, though is that I always get a “Object reference not intitialized” error in the Controller’s SaveChanges method when I delete a session. Everything else works fine.

    [HttpPost]
    public SaveResult SaveChanges(JObject saveBundle)
    {
    return _contextProvider.SaveChanges(saveBundle);
    }

    I will try the final Github code to see if there is something missing in the courses final code.

    Thanks for saving my career, John.

    Dudley

    • Dudley

      Same problem with the final code.

      Try to delete a session and I end up with an “Object reference not intitialized” in the SaveChanges method of the BreezeController.

      Is this just me?

      Thanks in advance.

      Dudley

      • Samuel

        No, i also have the same issue!

        • Morgan

          Did you resolve this Samuel?

      • John

        There was a bug in an older version of BReeze. Upgrade and it should be fixed.

        • Samuel

          After a Breeze update from nuget, i get the error no load:
          “Error retreving data. Metadata query falied for :api/Breeze/Metadata; NaN

          • John

            Samuel,

            It looks like there was one breaking change that affects CodeCamper JumpStart (CCJS) in Breeze. The WebAPI routes were changed from /api to /breeze so they won’t conflict with other api routes. Once I installed breeze 1.3.2 I got your error, but then I changed line 10 in config.js and it worked.

                var remoteServiceName = 'breeze/Breeze';
            

            I also updated the GitHub repository to reflect this.

          • Morgan

            Once I follow the procedure above I get an error on “select” clause of my getpartials. Unable to locate property ‘Id’ on typ. If i change my to api route from /breeze/Breeze/Speakers?$orderby=Id&$select=Id%2CFirstName%2CLastName%2CImageSource to http://localhost:51724/breeze/Breeze/Speakers?select=Id%2CFirstName%2CLastName%2CImageSource$orderby=Id It works at least the call. Any Ideas?

          • Ward Bell

            Although there is a semantic difference it shouldn’t matter in your example. But I can’t repro this against the CodeCamper. Here are two query URL’s sent to the same endpoint. Both work. [1] http://localhost:53444/breeze/Breeze/Speakers?$select=Id%2CFirstName%2CLastName%2CImageSource&$orderby=Id and [2] http://localhost:53444/breeze/Breeze/Speakers?$orderby=Id&$select=Id%2CFirstName%2CLastName%2CImageSource

          • Morgan

            Firs! Thanks Ward for your time and efforts!

            Please correct me if I am doing anything wrong here:
            1) Update-Package Breeze.WebApi -version 1.3.2

            2) Change line 10 at config.js from var remoteServiceName = (‘api/breeze’); to var remoteServiceName = ‘breeze/Breeze';

            This changes the BreezeWebApiConfig.cs tile routeTemplate: routeTemplate: “breeze/{controller}/{action}”

            after following these simple steps I get the following message: Error getting data. Unable to locate property ‘Id’…ExpandBinder+SelectSome`1[Data.Class

          • Ward Bell

            I don’t know about v.1.3.2. We’re at 1.4.5 now. What you did makes sense but there are so many opportunities for things to be different. Sorry I can’t spend more time with you on this.

          • Morgan

            Thanks anyway Ward and may the force be with you!

  • Dudley

    Excellent. Thanks for the quick reply from everyone. This tutorial is excellent. The coding style is also excellent, so one learns the new technologies and good practices at the same time.

    Dudley

  • Jeroen

    Thanks, was waiting for this for a while :). You’re pluralsight training was great to follow.

    1 little issue, header now shows ..

    • John

      Jeroen,

      The title used to be derived from the router’s route property for “name”. It now uses “caption”. So you can change this. I am testing the change with the repository, but I want to be careful to not change the github repo too much from what is in the videos. For example, you can do this in config.js

      var routes = [{
              url: 'sessions',
              moduleId: 'viewmodels/sessions',
              name: 'Sessions',
              visible: true,
              caption: 'Sessions',
              settings: { caption: ' Sessions' }
              }
      
      • http://www.nextgendigitalhome.com Craig

        The router.onNavigationComplete event is also overridable – which means you can restore the old behavior by adding the following lines in John’s main.js file:

        //existing code…….
        // Adapt to touch devices
        app.adaptToDevice();
        //Show the app by setting the root view model for our application.
        app.setRoot(‘viewmodels/shell’, ‘entrance’);

        //new code below…
        // override onNavigationComplete behavior to use name instead of caption
        router.onNavigationComplete = function (routeInfo, params, module) {
        if (app.title) {
        document.title = routeInfo.name + ” | ” + app.title;
        } else {
        document.title = routeInfo.name;
        }
        };
        //end of new code
        });
        });

  • Ishraq Ahmad

    Thanks John,
    Latest code is throwing following exception,
    Metadata query failed for: api/Breeze/Metadata; Multiple actions were found that match the request:
    System.String Metadata() on type CodeCamper.Controllers.BreezeController
    System.Object Lookups() on type CodeCamper.Controllers.BreezeController
    System.Linq.IQueryable`1[CodeCamper.Session] Sessions() on type CodeCamper.Controllers.BreezeController
    System.Linq.IQueryable`1[CodeCamper.Person] Persons() on type CodeCamper.Controllers.BreezeController
    System.Linq.IQueryable`1[CodeCamper.Person] Speakers() on type CodeCamper.Controllers.BreezeController

    After changing App_Start\BreezeWebApiConfig.cs file, line no, 18,
    from
    routeTemplate: “breeze/{controller}/{action}”
    to
    routeTemplate: “api/{controller}/{action}”

    It worked. May be you have missed checking-in changes?

    • John

      Ishraq – I checked in routeTemplate: "breeze/{controller}/{action}" as that is the new reout eyou need for the new version of Breeze. The client then also needs to be changed, which I did in the config.js file. So it’s the way it should be … or at least it works here :)

      • Henk

        It’s strange, when I start the session from VS I get the same exceptions as Ishraq above, but when I then browse to the application using the IIS Express menu it works fine. BTW, I found that Ishraq’s BreezeWebApiConfig.cs fix above works for me too. Thanks John, ‘love your work!

  • Gang

    Hi John,

    I’m learning a lot from your SPA course on PluralSight. Thanks a lot for sharing and you’re really good at it! I’m working on a project where SPA is our goal. But I’m kind of lost of which way to go so your opinion would be greatly appreciated. We are deciding on whether to use durandal or backbone. I would love to go with durandal since we already uses knockout, but I’m concerned about two things, first being whether durandal supports activating two partial views at the same time due to our requirement that a context sensitive navigating tree (has its own view model) should be visible at all times along with a context sensitive details screen (has its own view model); second being that we already have substantial code that uses require.js, since durandal embeds require.js already, would that cause a problem?

    Thanks a lot!

    • John

      Gang – Glad you like the course :)

      With your Knockout and Require.js investments, I recommend you use Durandal. Durandal can certainly handle multiple views in different div’s in your shell view. Look at the compose binding and you can use that in several places. You can then activate 2 views in one shot based on some code too. There are doc sthat help explain most of this at durandaljs.com

      I think you are on the right track.

      • Gang

        John,

        Thanks for getting back to me so quickly. I’ll do some research on the compose binding and durandaljs.com. Again, really appreciate your help.

  • Mathew

    Hey John,
    Fist off, thanks so much for your SPA work, we are heavily considering using your Hot Towel Template as our basic standard for SPA in our company. I was wondering if you knew any good tutorials on javascript promises? Pluralsight has a very small section on them in the JavaScript Design Patterns course, however, I was wondering if there was one that was more extensive one or a good book on them. I know I struggle with it and I have a feeling that the rest of our developers will as well. Thanks again. P.S. Enjoying your public speaking course. Quick funny presentation horror story.. someone (definitely not me ; ) wink) miss spelled ‘public’ in a presentation once, forgot the L.. I’ll let you figure out the new word

    • John

      Mathew – Thanks, glad you like the SPA work and Hot Towel. I don’t know of any good tutorials on promises, but it is something I could easily blog. Can you elaborate on what you are looking to learn? I tend to use Q these days for promises, as jQuery’s seem a bit awkward to me. Let me know what it is you;d like to see and perhaps I can blog about it. If its long … feel free to email it to me on my contact page.

      • Mathew

        Hey John – So I looked through the api briefly and I’m getting a better understanding of Q. Q is basically used as a cleaner method to callbacks, is that correct or is there more to it than that? Basically, I’m a little confused on how to pass in parameters to the next function in the promise chain and on how to handle rejection reasons/error handling. On a higher level, a promise just a wrapper around an asynchronous javascript call correct? If that is so, is it better to keep your variables global to the view model and not pass any variables into the promise chain to lighten the dependencies the promise has to worry about? Thanks for being so accessible, I’m an intern and following your work has been a renaissance for me and game changer for mobile development for the company I’m at. I love how an interns get to talk to Regional Directors in this field, crazy stuff

        • John

          Mathew,

          Q (promises really) is just an easy way to use async calls and chain them together. Think “await” in C# … kind of :). Q is just one library that handles promises. jQuery does it too. But I like Q’s style better, personally.

          I wrap all my methods in functions and then chain them with promises. Makes it easier to read. You can grab return values from a previous call in the chain to the next call, too. I wouldn’t try to make variables global.

          Glad you are enjoying it all!

          • Samuel Pinto

            Hi John, a simple question:
            The activate function MUST return a promise?
            I am asking this because i am working in a simple spa using hot towel and, the navigation does not work in most of android phones…[old versions]

          • John

            Samuel – Activate must return something so the promise will resolve. You could just return true. I spoke with Rob from Durandal, and he has not seen any issues on Android either. If you do, open an issue on github for Durandal with reproducable steps.

          • Samuel Pinto

            Navigation in old versions of android should be done using the navigation method instead href #.

            data-bind=”click: $parent.changeNavigation”
            vs
            data-bind=”attr: { href: hash }” –> did not work in android 2.3.X

  • Pingback: Spa Jump-Start | Moretto Carlo

  • Jim Hoagland

    John,

    First let me say thank you for such a fantastic tutorial – a great education! I’m confused about where the firewall exists, and what technology is used to get the data requests thru the firewall. Is that the WebAPI’s job?

    Thanks,
    Jim

    • John

      Jim,

      Firewall’s usually allow HTTP traffic. You can also secure the Web API calls with ASP.NET authentication and use SSL.

  • Patrick

    John –

    I know a lot of questions have risen about security and securing web apps – do you have any blogs or other discussions you recommend to find the right authentication methods for Single Page Applications? I have spent a better part of the day reading about the recommended methods for intranet/web applications and watching Scott Allen’s videos on PluralSight for Mvc application security but there seems to be a lot of conflicting opinions.

    Thanks for your time.

    • John

      Patrick,

      Scott’s videos are excellent and very highly regarded. I’d point you there first. You can also check out the in-the-box SPA template with VS 2012 Update 2. It has an auth example built in.

  • Gary

    Hello John,

    In your DotNetConf presentation, you mentioned that Gmail is (or could be) a collection of SPAs. I believe you also made mention that if it were an ASP.NET MVC-based collection of SPAs, you could have different controllers serve up the different SPAs (or something like that).

    Could you expound upon that idea and how would you implement it (using MVC, Web API, and the js libraries/frameworks from your SPA jump start)?

    I’m trying to envision and develop a web app that is a collection of SPAs. There would be a shell/container for all the different SPAs. I think I’m wanting to use MVC areas to separate out all the different functional areas of the whole app, including an Admin SPA. At this point, I’m not seeing the forest through the trees in how to make Durandal (and the js libraries/frameworks) work with MVC areas (and the normal MVC stuff) to produce an app that is a collection of SPAs.

    Thanks!

  • Joshua

    How does this approach work with Google Analytics? Will GA automatically trap the views or is it necessary to create some sort of event mechanism to register them?

  • emi

    Hi John, great tutorial on Pluralsight. I was just trying to expand the example with nested ko bindings.

    Scenario is
    1 order has many items

    viewmodel:

    return datacontext.getOrders(orders);
    

    datacontext:

    var getOrders = function (ordersObservable) {
                var query = entityQuery.from('Orders').expand('Items');
    ...
    ordersObservable(data.results);
    }
    

    view:

    <section data-bind="foreach: orders">
        <div>
            <section data-bind="foreach: items">
                <p data-bind="text: description"></p>
               </section>  
         </div>
    </section>
    

    At this point the binding fails for “items”.
    I read something about Breeze not loading child entities 1-to-N in data.results unless you configure the Metadata retrieval as bidirectional. Any thoughts on this?

    • http://www.breezejs.com Ward Bell

      @emi – You do not have to have bi-directional navigation properties. Your *items* can be reached from your *orders* if the metadata prescribe an *Order.Items()* navigation property. This is the 1..N direction. You can omit the inverse navigation (*Item.Order()*) if you wish. If you have a specific failing example, we’d like to know about it on StackOverflow, please tag your question with “Breeze”

  • CCPony

    Hello John. Thanks for another great course in Pluralsight. I enjoyed it.

    There seems to be problems with durandal’s deactivate event. Using your CCJS-Scratch application: navigate to any session detail and change any field value. Click the “Back” button. Click the “Back” button again.

    Using Chrome, the browser behaves as expected.
    Using IE9, the confirmation message appears twice. Otherwise, the browser behaves properly.
    Using Firefox, the browser loses track of its navigation and stalls.

    I don’t know if this is a problem with Durandal or Sammy.

    Are you aware of this problem and if so, can you suggest a solution?

  • http://MMS Ping Yi

    HI John,
    Now I am learning SPA. I feel your Hot Towel template is a nice frame.But I meet a problem now. as below
    NewFactory.js
    function activate() {
    logger.log(‘NewFactory View Activated, Hello guys’, null, ‘NewFactory’, true);
    document.getElementById(‘fileInput’).uploadify({
    ‘height': 30,
    ‘swf': ‘/scripts/uploadify/jquery.uploadify.swf’,
    ‘uploader': ‘/HotTowel/Upload’,
    ‘width': 120,
    ‘onComplete': uploadComplete
    });
    return true;
    }

    NewFactory.html

    I can’t access the element by id of the page in viewmodel function activate().Could you tell me how to access it when page initialization?Thanks very much.Waiting for your replay.

  • Togi

    Hi John

    Is there any diagram which shows the process of the application?

    As a new SPA and web developer, it is not easy for me to understand the whole process by looking the source code of the application.

    What I mean, how can I see which page or js library works in which step? (like a technical sequential diagram)

    Thanks a lot for your answer in advance.

    • John

      Hi Togi – That’s a good idea. I’ll create something and blog it when I get some time.

      • Togi

        Great…waiting for it…

        I would like to ask one more question to you.

        Can you explain what are the advantages of using your template (Hot Towel or the way that you used in SPA JumpStart) rather than using the SPA template in asp.net web tools?

        For instance at official asp.net web site, there is an example which uses the other template and in a different way. (MVC)

        http://www.asp.net/single-page-application/overview/introduction/knockoutjs-template

        As I see, using Hot Towel Template I can implement my application in MVVM pattern and with the help of other useful JS libraries (Breeze, Q, Sammy etc.) I can implement more responsive and robust SPA application.

        Is there any other advantage that you say?

        To be honest, the hot towel template and the SPA Jump Start Code looks more complicated than ToDo example which is done using the template in asp.net web site.

        However, I would still like to do my application with your template, since the solution structure and JS libraries that you used makes the application more solid and extendable.

        May be it hurts at the beginning but later I will be more happy with hot towel :)

        Thanks

  • Nazeem

    Hi John,

    First of all, thanks for this great course and other courses like knockout. How to make intellisense work for bootstrap?

    Thanks

  • Armand

    Hi John,

    Where can I find the source code the same on what you had presented in the pluralsight. I am having hard time returning the different IRepository in the WebApi Controller. It seems that there are not exposed even though it has a public modifier. Thanks

  • Matteo

    Hi John, are you going to make another SPA course in the next months?
    I see that Breeze’s TempHire has been released yesterday and it includes interesting features like Repository / Unit of Work patterns both server-side and client-side, and handling MVC authentication. It would be great to have this features explained in a sort of “update / add on” to your JumpStart course.
    Thank you, Matteo

  • Togi

    Hi John

    I downloaded the source code of code camper and trying to understand the codes. There are lots of JS codes which are quite specific to used libraries. The problem that I have those functions does not have any comments.
    Some of the function names describe themselves really good. However, lots of code statements not easy to understand.

    What do you think about that?

    Do you think to update the source codes with some additional comments?

    Thanks

  • Jesse P

    I am wanting to upload files to the add session screen, for example, how would I associate these files to this session?

    Also asked here: http://stackoverflow.com/questions/16797048/breeze-spa-upload-files

  • Leo

    Your course on pluralsight is amazing. What I would love to see is how could we upload an image when saving an entity. I started an app with the base you taught on your SPA videos and although I can upload the file fine, I would like to know how could I do this the “HotTowel way”. If I want to allow the user to insert new Speakers, how would I handle the user image upload?
    Thanks for your work.

    • Jesse P

      I would like to see this as well.

  • Greg

    Sweet! ..thanks.

  • David

    Hi John, thanks for the great tutorial and application. I am wondering why in nav.html you create the Admin drop down menu with a foreach statement and then bind the click event to $parent.addSession.
    Surely other admin routes will not want to be bound to that function. Would it not be better to simply bind the href attribute to the routes hash as done for the visible routes?
    Cheers,

    • Samuel Pinto

      Hi David the name was not clever, if you check in shell.js
      you have:
      function addSession(item) {
      router.navigateTo(item.hash);
      }

      i have change it to this name:
      function changeNavigation(item) {
      router.navigateTo(item.hash);
      }

      this function navigate to the root defined in config.js… using router.js

      This is the way i get it… if i am saying something wrong, please correct me…

      • John

        Samuel – Yep. Binding to a function is the way to go. The function could be generic like that, or you could also databind the function name … either way its fine.

    • John

      David – Yes … that would be better :)

  • David

    Further to my last… I have implemented attribute binding and am getting some strange behavior. Firstly, the Admin menu stays expanded after the sub-menu has been clicked. I suppose that would be an easy css fix. More importantly I am finding that when I go to my edit pages and then navigate away from them by clicking other menu items, I end up with the wrong mix of view and view model. I will have (for example) the Home view bound to the projectadd view model.

    • John

      David – Bootstrap had a bug in it where the href binding would keep the menu open. If you use the click binding and create a matching bound method in the viewmodel, it will close.

  • Alexandre Hedreville

    Hi John

    I have really enjoyed your course

    I am new on web development and after two 1 month and half reviewing your code, and your explanation.. today at 1:00 at night at have finished

    I have study your course by nights, and now I have a more clear idea about SPA and how to use it

    Your course is excellent, even If my mother language is the Spanish I have been able to follow it

    My congratulations for this excellent course

    Just a final question…

    I would to know.. just a quick idea.. just to help me to figure the way to code and display this relations

    1) How breeze could manage the 1 to many and many to many relations..
    For example the relations: person1_*attendance or for example a standard business relations like 1 category may have * items and 1 item may have *categories

    2) With kind of HTML element should I use for the UI, a list box with multiple select? a unordered list ? a check box list?

    Thanks a lot

    Yours sincerely / Un saludo

    Alexandre Hédréville Pérez
    IT Supporter
    Field Support MED

    Vestas Shared Service Center
    T +34987 84 55569
    ALHPE@vestas.com
    http://www.vestas.com

    Company reg. name: Vestas Eólica SAU
    This e-mail is subject to our e-mail disclaimer statement.
    Please refer to http://www.vestas.com/legal/notice
    If you have received this e-mail in error please contact the sender.

    • John

      Alexandre – Thanks for the feedback.

      There are examples in the course for 1 to many, as you mention. Breeze manages these quite nicely so you can have a category that applies to many items/products. Check my examples or the breeze web site examples for more. If you need specific help with your sample code, post it to StackOverflow (always a good idea).

      If you need to select a category for an item, a drop down list works great.

      If you have a many to many selection (like people and attendance in my course), then it is up to you and how your users can best use the data. Am Attendee view might have a list of sessions they can search and attend. A Session view might have a list of attendees that can be selected for it. The paradigm is really up to you.

  • Samuel Pinto

    Hi John,

    A simple question,
    why in navigation i have some images constantly reloading?

    Example:
    http://i.imgur.com/tKDVkNj.png

    All other photos are defined in CSS…

    I can´t understand why just this photo is reloading! [ i must use CSS? ]

    Do you know why?

  • serkan

    Hi John thx for brillient codes and your tutorials very clear have a nice day == night

  • jose velez

    what happened to the best part of you code? The repo pattern. I used to go to this source as a reference for all my projects.

    • Ward Bell

      The repo/unit-of-work pattern is in full flourish on both client and server in John’s Angular course. That’s not open source but for a month of Pluralsight you can get it.

  • Monte Baker

    I know that the primary focus of your development is client side, but I am hoping you can point me in the right direction. I am trying to leverage SPA’s in my organization for small vertical application connecting to VLDB’s as such I need a dev stack something like
    Poco
    Small Entity Model
    huge database.
    I have had zero success at finding any examples or figuring out the best way on my own to integrate breeze;(durandal/angular) into a database first EntityModel based connection. can you direct me to any learning source to get me caught up?

    • Ward Bell

      ZERO? There are a bunch of samples on the Breeze site that fit this description (except for “huge database”). What aren’t they telling you? Help us help you.

      • Monte Baker

        perhaps it is just my ignorance, but in all of the breeze examples I have found they are generally approaching the solution using a code first solution. I am trying to evaluate SPA as a replacement in my organization for SL5 development apps. I have been very impressed with the capabilities that i have seen as far as Rich UX, however from my teams development perspective we are often connecting to existing Enterprise VLDB’s (SQL/Oracle) with existing entities, schemas etc. so the idea would be to create a TT4 EF and import objects (client.client = client, client.order = order) or some such and allow developers to build there own API and client methods to those entities. in my practice attempts i have had difficulty in creating basic CRUD operations to this environment (absolutely could be lack of education) but it does make me wonder if the only way to do SPA in the enterprise the way i am looking at it is to utilize the “Data from a 3rd party service” method.

        • Ward Bell

          Sounds like a big task. You might consider contacting us at breeze@ideablade.com if you’re open to our consulting services.

  • Ayesha Ikram

    i was following the jump start course. in model.js we see a code like personInitializer which creats a fullName a property that does not exists and we create it for the view. My concept is that it is something we are doing to support a view so these kinds of codes should be in ViewModel instead of Model. what do you say ?

    • Ward Bell

      I get your point but this one is in a grey area for me. You could say that we were creating it only for the view. But that isn’t necessarily the case. The `fullName` is generally useful and is not tied to a particular form of display. For example, I might use it to compose a debug log entry. If it were something UI-specific (say, ‘isEditing’) you’d have a more persuasive point. As it is, I think the convenience of it as well as its generality is sufficient to overcome any concern I have about muddying a model object with presentation concerns.

%d bloggers like this: