Integrating a Twitter bootstrap UI application into IBM Connections and MS SharePoint

In the last 12 months I have twice presented at MWLUG 2014 and ConnectED 2015 (with Mark Leusink) on how to run a  Domino/Angular.js application in IBM Connections and SharePoint. One of the hurdles to doing that was to figure out how to integrate bootstrap with the OneUI layout of Connections and MS SharePoint built in style.

Beyond the Everyday

This was the original http://beyondtheeveryday.com application which Mark Leusink built (for ConnectED) based on Bootstrap CSS. My job was to make it run anywhere – in this example IBM Connections. The same process described here is also used to make the application look nice in SharePoint.

c4

To do this I used an HTML Widget installed on the Connections server and with some JavaScript trickery (as explain at the conference) I was able to insert the BTE application into the Connections HTML widget relatively easily.

However – the functionality was not the immediate issue – the look and feel was.

IBM Connections uses the IBM OneUI Stylesheet for look and feel. Both OneUI and Bootstrap set default fonts and sizes on every page element and when mixed together in the wild things go badly wrong. As you can see from the image below – the bootstrap is fine – but the addition of another CSS which affects HTML and Body messes with the existing OneUI style.

c1

So the quick and dirty solution to me was to stop bootstrap from affecting everything else in the BODY of the connections page. In this case to maintain look and feel with OneUI – remove everything affecting the OneUI look.

I took an un-minified version of Bootstrap and removed the first 1400(ish) lines of code – down to the first media query. This removed default font size etc for every default HTML tag.

c3

 

This solved the problem.

Do not do this in production boys and girls – use a properly modified bootstrap file which only contains the CSS you need! Depending on the complexity of your application you may have to do other modifications to get your application looking good.

c2

Sharepoint

The process is identical for adding the application into SharePoint, although in that case I used an embeded code widget within a SharePoint page to insert my HTML/SCRIPT.

c5

#lazy #productive

 

BTE102: The Demonstration application – beyondtheeveryday.com

In the previous post  I described how Mark Leusink and I are going to be speaking about Angular.js in our presentation at ConnectED later this month.

We are very proud to announce the demonstration application upon which the presentation will be based

http://beyondtheeveryday.com

This application was created by Mark Leusink and is an amazing example of how simple an Angular application can be integrated with Domino data. The application is fully responsive and is particularly nice to use on a mobile device. All credit goes to Mark for this, I am very flattered to be talking with such an astute and talented developer. You can find out more about the application from Mark’s blog – http://linqed.eu/2015/01/14/marky-marks-mobile-first-connected-sessions-demo-app/

The application is running on a Domino server.

b1

IMG_0339

During the presentation we will demonstrate how we got the application to work on a node server hosted in Bluemix and also demonstrate the application running on SharePoint, IBM Connections and as a native Mobile application.

If you are still not sure, listen to Pete Janzen talk about his recommendations for the conference 😉

Write once – run anywhere………………. !

BTE 102: The Future of Web Development Write Once, Run Everywhere with AngularJS and Domino

Mark Leusink and I are very excited to be presenting a session at ConnectED this coming January. This is a great opportunity to come and find out about something a little different from the normal XPages run of the mill development. Mark and I will provide an introduction to the concepts and structure behind Angular.js, and then demonstrate how to build a very simple yet useful application using Angular.js and a Domino data store.

We are also going to blow some minds by showing the same application running on non-Domino platforms. If architected correctly, this transformation can be made with almost no code refactoring at all.

Come and see us in Orlando !

http://www.ibm.com/software/collaboration/events/connected/

Marky, Mark

 

Track: Beyond the Everyday

Abstract

AngularJS is currently the most popular JavaScript MVC framework. It’s driving more adoption and interest in the MVC/ REST API application architecture model. The ease of use, portability and re-usability of the code makes it an ideal solution for modern web developer needs. We’ll show you how to use AngularJS to modernize your existing Domino apps, while leveraging Domino’s best features. The speakers will also demonstrate how the power of architecting a solution based on AngularJS allows your Domino application to be made available through other platform interfaces. Taking “Write once, run everywhere” in the literal sense, you will see the same Angular/ Domino based app running natively in XPages, IBM Connections, Bluemix, IBM Worklight and more. Client-side JavaScript frameworks such as AngularJS are the future of web development – come and see it in action. 

Angular in XPages: Formatting Domino Data Services Date values with app.filter

In this article I will show how we can use the core angular date filter capabilities to format Date format, Domino data into an Angular.js based application

Introduction

In previous articles I have shown how to create a simple Angular.js application using a notes Domino Data Services feed from a notes database. If we want to add “date” information then we need a way to nicely format it. Using the Angular.js documentation page as reference I will show you how we can do this with Domino data.

Adding dates to our view

When we add a date field to a Domino Data Services feed we get something which is to the human eye pretty “ugly”

a1

And when we add lastModified into our template, it is well, less than appealing….

a2

 

Adding a formatting function to the template

We can modify the template to use a formatting function by changing up the template slightly and then adding a formatting filter to the application.

In the app.js we add the following

personApp.filter("formatDate", function () {
    return function (x) {
        return new Date(x);
    };
});

And then we reformat the template as such:

    <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 class="user">{{person.lastModified | formatDate | date:"dd MMM yyyy" }}</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>

The critical part is {{person.lastModified | formatDate | date:”dd MMM yyyy” }}.

The documentation unfortunately is not clear on this and I found this Stackoverflow example which worked perfectly. http://stackoverflow.com/a/25856275/1171653

The resulting page now looks formatted and much easier to read

a3

Conclusion

I spent which a lot of time failing to achieve this date formatting without doing it the angular way. One quick google (or three) and I had the answer. Do it the angular way and oo look that that nice and simple formatting.

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

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 🙂

 

 

 

 

 

Chart Directives and Dynamic Binding – MWLUG 2014 preview

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 🙂

 

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

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.

Working on my MWLUG2014 presentation

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 !!!