Xomino

Domino with the new improved X

Running an XPages/Angular.js application on a Bluemix site

Posted by mark roden on September 17, 2014

In this article I will show you how to run an XPages application based on Angular data within a Bluemix based website.

Introduction

For background reading on this article please review my series on Angular.js in XPages starting here. I will be using the application described within that article as the starting point for this article.

A little background on Bluemix

Bluemix is IBM’s new Platform as a Service (PaaS) system which provides the end to end cloud based hosting of application services. For more information check out www.bluemix.net and read up/follow Ryan Baxter‘s blog. Bluemix provides cloud based services including many things ranging from MongoLabs hosting and SMS sending to Node web servers and Static sites.

You can register for a 30 day free trial of Bluemix from the previous link. I strongly suggest you look up bluemix videos on You Tube first to get an idea of what is possible.

For this example we will be creating a static site. And it is really rather simple.

Loading my site into Bluemix

You will need to set yourself up with Cloud Foundry – using the instructions on the Bluemix site. Look at the Quick Start instruction for installation of the Cloud Foundry files. These are the command line tools which are necessary to post your site from local machine to the bluemix site. There are other ways but this is the way I did it.

This entire process took less than 30 minutes – Ryan Baxter is a Bluemix Advocate and it is his job to sell this stuff and help :)

from a Skype Conversation

[8/25/2014 11:26:01 AM] Ryan Baxter: hey

Talking about Beer and Angular and Bluemix…..

[8/25/2014 11:36:25 AM] Ryan Baxter: try this
[8/25/2014 11:36:26 AM] Ryan Baxter: https://github.com/cloudfoundry-community/staticfile-buildpack
[8/25/2014 11:36:37 AM] Ryan Baxter: cf push -b https://github.com/cloudfoundry-community/staticfile-buildpack
[8/25/2014 11:36:52 AM] Ryan Baxter: just for hosting static files

and after that – looking at my Bluemix log it took 13 minutes of bug fixing and stupid idiocy to get this up and running – SWEET !!!

  1. I exported the application files from my database:b7
  2. I used the cf tool to create the Bluemix static site and and upload the files (from my c:\xominode folder)b5Looking at the bluemix site I can then see the created static site
    b3 b4
    Looking at the App through the Bluemix interface you can see the files within the applicationb8
  3. I created the necessary CORS headers through my IHS domino.conf file (See this article)
  4. I restarted my Domino HTTP server task
  5. Repeat and debug ‘cos I am an idiot
  6. Voila my Angular.js app running in Bluemix

b1
b2

When I say running in Bluemix I really mean that – because all the files are loaded up on the Bluemix site (view source below) – this truly is a Bluemix hosted application.

b6

 

 Conclusion

While there are many services available in Bluemix for running applications in the cloud, you can also use it to host static websites which use data from non-Bluemix sources. I am not sure there is a practical implication for the example shown above, but you never know. There are always going to be people way smarter than me :)

 

 

 

 

 

Posted in Angular in XPages, Angular.js, Bluemix, XPages | Leave a Comment »

MWLUG 2014 Slide Deck – Write once, run anywhere: Angular.js in XPages.

Posted by mark roden on September 2, 2014

Here is the slide deck for those interested – thank you to everyone who attended the presentation and I look forward to talking more on the subject in the future.

http://www.slideshare.net/MarkRoden/angularjs-in-xpages

 

 

Posted in Angular in XPages, Angular.js, MWLUG | 3 Comments »

Going to MWLUG 2014? You need to buy these guys a beer as well….

Posted by mark roden on August 24, 2014

—->>>> Richard Moy <<<<—

He’s the guy you really need to thank for this event – without his dedication and enthusiasm, the most significant User Group meeting in North American this year would surely not happen.

 

Mike McGarel

helps on the web site,

Devin Olson

was the boots on the ground and help

 

Ray Bilyk

 

Be Warned though – Devin and Ray are VERY particular about their beer – Richard and Mike not so much – so ask first ;)

Posted in Just Marky, MWLUG | Leave a Comment »

Going to MWLUG 2014? Buy Dave Leedy a beer

Posted by mark roden on August 24, 2014

Yeah I know I have rattled on about this before but it holds as true today as it does any other day before.

Here is a list of reasons you should buy Dave Leedy a beer in case you were wondering…

1) really? You need a list?? Shame on you….

2) NotesIn9 has helped you – One of those videos by Dave, John, John, Brian, Chris, Graham, Jeremy, Mark, Mark, Paul, Peter, Steve, Tim, Chris, Paul, Josh, Dan, Niklas, Michael, Russ, Serdar, Sean, Mark, Brad, Frederick, Steve, Richard, Kathy, Stephan, Keith, Martin and Andrew (to name but a few) made you look better to your boss

3) Dave pays for this amazing service out of his personal pocket. By my reckoning $40 a month for 3+ years is well over $1000 dollars. A $5 beer is the LEAST you can do to repay him.

4) Dave refuses to take contributions – if it would make a difference I would do a kickstarter, but he’d refuse.

5) NotesIn9 is the largest repository of videos and tutorials, created by the largest number of different contributors in the IBM ICS community.

If he refuses to let you buy one, buy it anyway and put it in front of him. He’s going to be there for four nights so just do it.

Buy the man a beer – you owe him and it would be rude not to!!!

The line starts behind me……..join it !

Posted in Just Marky, MWLUG, NotesIn9 | 3 Comments »

Chart Directives and Dynamic Binding – MWLUG 2014 preview

Posted by mark roden on August 20, 2014

Although not directly related to the purpose of the presentation I am going to demonstrate how to use an Angular.js chart directive to bind to the application service data and create dynamic charting within the application.

m1

Changing the Zip for 1 Marky not only updates the data displayed – but also because of the data bind – auto-magically updates the chart

m2

While this in itself does not directly relate to the write once and run anywhere nature of the presentation – it does demonstrate componentized Angular.js code writing which you *might* want to write once and run anywhere……

Come and see the presentation to find out more :)

Remember to stick around until the end I am on at 3pm Friday in the main room :)

 

Posted in Angular in XPages, Angular.js, MWLUG | 6 Comments »

Accessing the original element when using Select2-focus

Posted by mark roden on August 17, 2014

In the application we are currently working on I wanted to add an ajax call to a JSON service, but only for certain fields. Rather than go through the application and add the code to every element I used a delegated focus event for the field with an attribute of  “help_fieldName”. The following HTML represents the code on the form:

          <div class="col-lg-8">
            <select help_fieldname="territory">
              <option value="UK">UK</option>
              <option value="US">US</option>
              <option value="Global">Global</option>
            </select>
          </div>
          <div class="col-lg-4">First Name</div>
          <div class="col-lg-8">
            <input type="text" class="form-control" help_fieldname="firstname" />
          </div>
          <div class="col-lg-4">Last Name</div>
          <div class="col-lg-8">
            <input type="text" class="form-control" help_fieldname="lastname" />
          </div>

The following jQuery code makes it work. The getHelp function shows/hides the help based on the boolean in the function.

$(document).ready(function(){
	$('body')
		.on('focus', '[help_fieldName]', function(){
		     getHelp(true, $(this))
		})
		.on('blur', '[help_fieldName]', function(){
		     getHelp(false, $(this))
		})
	})

 

What I found though was that when I used Select2 the field attribute was not being picked up. This is because Select2 creates it own DOM elements to display the field and the original field attributes are not transferred to this new DOM structure.

So I needed to come up with a way of accessing the original element from the select2. This turned out to be very simple – select2 emits an event on focus and blur called select2-focus and select2-blur. The event target gives me direct access to the original field the select2 is representing.

Using this simple modification to the delegation code I was able to access the help_fieldName to pass to the help Function. The image below shows the console.log, highlighting the underlying DOM element.

$(document).ready(function(){
	$('body')
		.on('focus', '[help_fieldName]', function(){
		     getHelp(true, $(this))
		})
		.on('blur', '[help_fieldName]', function(){
		     getHelp(false, $(this))
		})
		.on('select2-focus',  function(e){
		     console.log(e.target)
		     getHelp(true, $(e.target))
		})
		.on('select2-blur',  function(e){
		     getHelp(false, $(e.target))
		})
	})

s1

Posted in jQuery | 2 Comments »

Angular in XPages #8 – Directives (did someone say plugins?)

Posted by mark roden on August 10, 2014

In this article I will discuss Angular Directives and why they are near and dear to my heart

Directives

Directives in Angular are modular pieces of functionality which in some cases are very analogous to plugins in jQuery. According to the Angular documentation…

“At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS’s HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.”

For more on the directive documentation look here – https://docs.angularjs.org/guide/directive

I have already shown and demonstrated some of the core Angular directives like ngApp and ngView. Those attributes within the HTML are the instructions to “Do Something Here”

<div ng-app="personApp">
    <div ng-view></div>
</div>

The on-last-repeat directive

Within my demo application I wanted to know when the table was finished loading. The problem is in Angular that there is no “I am finished with the template load” event. The reason is due to the asynchronous nature of the Angular code.

I wanted to load the table and then take an action on it. To do this I added a directive to the “repeat control” within my template for loading people.

The following example was completely plagiarized from this article – respect !

http://www.nodewiz.biz/angular-js-final-callback-after-ng-repeat/

You can see the on-last-repeat attribute within the first TR

    <tr ng-repeat="person in people"  on-last-repeat>
        <td>{{person.firstname}}</td>
        <td>{{person.lastname}}</td>
        <td class="zipCode">{{person.zip}}</td>
        <td class="user">{{person.username}}</td>
        <td><a class="btn btn-info" href="#/person/{{person['@unid']}}">Edit</a></td>
        <td><a class="btn btn-warning" href="#/person/{{person['@unid']}}/delete">Delete</a></td>
    </tr>

I then created a directive within my app.js to do something with the on-last-repeat

personApp.directive('onLastRepeat', function() {
    return function(scope, element, attrs) {
        if (scope.$last) setTimeout(function(){
            scope.$emit('onRepeatLast', element, attrs);
        }, 1);
    };
})

Within the code we are creating a custom “event” which can be listened for in another part of the application

  • If the last entry is triggeredhere
    then
  • $emit the onRepeatLast event within the application

Then in the PeopleListCtrl controller we set a listener -

  • $on the onRepeatLast event
  • Do something
peopleControllers.controller('PeopleListCtrl', ['$scope', '$http', 'peopleFactory',
    function ($scope, $http, peopleFactory) {
        $scope.$on('onRepeatLast', function(scope, element, attrs){
           alert('The table has loaded')
        });

a1

 

Well that is a little simple….

Yes it is but it serves to demonstrate the concept. The best part is that there are lots of people who are writing plug and play Directives for Angular – just like jQuery plugins. If I could be bothered I might even do some blog posts on useful Directives…..But is a good resource for looking at some available directives.

http://angular-js.in/

There are multiple directives for using jQuery plugins within an angular construct – this is very helpful for data binding. There are also multiple directives which are independent of jQuery and are stand along “Angular” plugins for want of a better term.

Posted in Angular in XPages, Angular.js, XPages | Tagged: , | 7 Comments »

Working on my MWLUG2014 presentation

Posted by mark roden on August 6, 2014

Just wanted to show a work in progress – screenshots of what I am working on for MWLUG2014. Part of the presentation is showing how to make your Angular applications portable.

My sample app will be the one I created as part of the Angular in XPages series.

I will walk through the code and demonstrate how I can take this stand alone application

a2

and insert it into this bootstrap demo dashboard application

a1

creating this fully functional component capability within the dashboard

angularinDashboard

 

With only 4 lines of HTML and zero XPages dependency.

Come to MWLUG2014 in Grand Rapids Michigan and find out more

PS

Make sure you plan to stick around to the end – I am not on until 3pm on Friday !!!

 

 

 

Posted in Angular in XPages, Angular.js, MWLUG, XPages | Leave a Comment »

Angular.js in XPages #7 – Writing better code using Services

Posted by mark roden on August 3, 2014

In this article I will discuss a better programming practice for Angular.js than was demonstrated in the previous articles within this series. I have mentioned before, part of the purpose this blog is very much a “learning in progress” for me. Without going through the previous articles I would not have been able to get to this point and write “better code”. Hopefully with that understanding, those of you who have been along for the ride will appreciate this and grow with me :)

Services within Angular

Within Angular there are these programmatic entities called services – and if you read around Angular programming practices (Follow @ToddMotto – http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/) you will find (as I have) that adding application logic within Controllers is generally frowned upon.

“In AngularJS world, the services are singleton objects or functions that carry out specific tasks. It holds some business logic. Separation of concern is at the heart while designing an AngularJS application. Your controller must be responsible for binding model data to views using $scope. It does not contain logic to fetch the data or manipulating it.”

http://viralpatel.net/blogs/angularjs-service-factory-tutorial/

From a maintainability perspective, as well as logical code layout perspective, having functional logic within the controller is akin to writing a 1000 line LotusScript agent  – not optimal !!

I used this article by Dan Whalin to better understand how to create a Service using a factory

So what changed?

We I changed the controller around so that code in the controller that once looked like this:

 $scope.createPerson = function(event) {
            $http({
                url: '//copper.xomino.com/xomino/ainx.nsf/api/data/documents?form=fUserName',
                data: $scope.person,
                withCredentials: true,
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                }
            })
                .success(function(data) {
                    location.href = "#/people";
                })
                .error(function(data) {
                    console.log('Error: ' + data);
                });
            event.preventDefault();
            return false;
        };

now looks like this:

        $scope.createPerson = function(event) {
            dataFactory.createPerson($scope.person, event)
                .success(function(data) {
                    event.preventDefault();
                    location.href = "#/people";
                })
                .error(function(data) {
                    console.log('Error: ' + data);
                });
        };

and the service looks like this:

    dataFactory.createPerson = function (person, event) {
        console.log(person)
        return $http({
            url: urlBase+'documents?form=fUserName',
            data: person,
            withCredentials: true,
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            }
        })
    };

 

Now I know you are looking at this and saying to yourself – hang on you just copied and pasted all the code and actually made it longer and more complicated – and that would be very perceptive of you – but (and I had to make this leap to believe it myself), it is better.

My example application only really has one purpose – manage people. In a more complex application a separation of logic into like components would make sense. By using the service I have separated all my “do stuff with people” out into a people Service. When I built the next part of the application – to do with buildings for example I would create a buildings Service and manage all my building logic there.

Let the controller do it’s job and bind the data to the View and keep your logic out of the controller and into Services.

The final Code

My service (service.js)

personApp.factory('dataFactory', ['$http', '$timeout', function($http, $timeout) {

    var urlBase = '//copper.xomino.com/xomino/ainx.nsf/api/data/';
    var dataFactory = {};

    dataFactory.getPeople = function () {
        return  $http.get(urlBase+'collections/name/byFirstName5Col?open&count=3').success(function(data) {
            $scope.people = data;
        });

    };

    dataFactory.getPerson = function (id) {
        console.log('get person')
        return  $http.get(urlBase+'documents/unid/' + id)
    };

    dataFactory.createPerson = function (person, event) {
        console.log(person)
        return $http({
            url: urlBase+'documents?form=fUserName',
            data: person,
            withCredentials: true,
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            }
        })
    };

    dataFactory.savePerson = function (person, event, id) {
        console.log(id);
        return $http({
                url: urlBase+'documents/unid/' + id,
                data: person,
                withCredentials: true,
                method: "PATCH",
                headers: {
                    "Content-Type": "application/json"
                }
            })
    };

    dataFactory.deletePerson = function (id) {
            var temp = confirm('Are you sure you want to delete?')
            if (temp){
                return $http.delete(urlBase+'documents/unid/' + id)
            } else {
                location.href = "#/people"
            }
    };

    return dataFactory;
}]);

My controller

peopleControllers.controller('PersonDetailCtrl', ['$scope', '$routeParams', '$http', 'action', '$timeout', 'dataFactory',
    function($scope, $routeParams, $http, action, $timeout, dataFactory) {

        $scope.create = (action=='new' || action=="delete");

        if (action=="get") {
            dataFactory.getPerson($routeParams.docId)
                .success(function(data) {
                    $scope.person = data;
                })
                .error(function(data) {
                    console.log('Error: ' + data);
                });
        }

        $scope.home = function(){
            location.href='#/people'
        };
        $scope.createPerson = function(event) {
            dataFactory.createPerson($scope.person, event)
                .success(function(data) {
                    event.preventDefault();
                    location.href = "#/people";
                })
                .error(function(data) {
                    console.log('Error: ' + data);
                });
        };

        $scope.savePerson = function(event) {
            dataFactory.savePerson($scope.person, event, $routeParams.docId)
                .success(function(data) {
                    event.preventDefault();
                    location.href = "#/people"
                })
                .error(function(data, status, headers, config) {
                        console.log('ErrorData: ' + data);
                });
        };

        if (action=="delete") {
            dataFactory.getPerson($routeParams.docId)
                .success(function(data) {
                    $scope.person = data;
                    $timeout(function(){
                        dataFactory.deletePerson($routeParams.docId)
                            .success(function(data) {
                                $scope.person = {};
                                location.href = "#/people"
                            })
                            .error(function(data, status, headers, config) {
                                console.log('ErrorData: ' + data);
                            });
                    }, 300)
                })
                .error(function(data) {
                    console.log('Error: ' + data);
                });
        };
    }]);

 

Posted in Angular in XPages, Angular.js, XPages | Tagged: , | 2 Comments »

Taking back productivity in Domino Designer (a NotesIn9 production)

Posted by mark roden on July 29, 2014

Yeah it has been a while (over 18 months) since the last time I did a NotesIn9 video but it finally happened again.

NotesIn9 149:  Database Resources and Design Definition

Doesn’t sound very exciting does it? Dave needs to work on his attention grabbing heading show names. I would have called it something more like this – but then who am I to complain – it is not my show after all ;)

NotesIn9 149:  Taking back productivity in Domino Designer 

This video revolves around some simple but not always well known facts about working with Domino Designer in Eclipse (DDE). When you use Database Resources and custom controls they slow up designer significantly. XPages developers unnecessarily put up with it and just curse out the DDE slowness. Take back your productivity and make your XPages quick again.

Using some architecting tips and the Design Definition within a custom control you can:

  • Speed up designer significantly
  • Continue to take advantage of the database resources
  • Layout your code in a more readable fashion within the DDE Design Pane
  • Take back your productivity in Domino Designer

 

Thanks as always to Dave for doing Notes In 9 – if you see Dave at MWLUG, ConnectED or any other time – buy that man a beer !!

 

Posted in NotesIn9, XPages | 1 Comment »