Building products and services for mobile and web? We're writing about how to stand out and make products that help people.

How to integrate your UI Widgets with AngularJS

When building apps we tend to create reusable code, which helps us in the long run, makes our code easier to understand and all in all cleaner. We like to build modular things.
This modularity that we’re used to shows itself not just in the units that we write but the in UI and elements that we build. Sometimes it makes sense to think ahead, and create our widgets for re-usability.

That is how the Mobiscroll UI Library is built. We created our AngularJS integration plugins for the components and we are going to show you how you can do it as well.

We can think of angular directives as custom html attributes or elements that define behavior for the element. For example if we want an image on a page that changes depending on a certain condition we can just write:

<img ng-src="http://www.gravatar.com/avatar/{{user}}"/>

<img ng-src="http://www.gravatar.com/avatar/{{user}}"/>

Whenever the user expression value changes, the image source will change too. The directive that is responsible for this behavior is the ngSrc. There is a set of built in directives that comes with Angular, like the ngRepeat, ngModel, ngView and so on. For more info and examples on the built in directives see the Angular documentation.

Custom directives let you define how the element should behave. Also the element can be the directive itself! Instead of creating the above img with ngSrc, you could create a directive called myuser and write it as follows:

<myuser />

<myuser />

Of course you will have to implement the actual behavior for the directive, but as you will see it’s not difficult at all.

Defining a directive is relatively easy. Inside a module you just give it a name, set dependencies if any and return an object with some basic options (this is called the directive definition object). We will also use a service called $parse (more on that later).

The link function will be called once for each element. This is where most of the custom logic comes regardless if we integrate a control into angular or create a new directive from scratch. For our calendar directive the initialization will take place in here. It is straight forward, since the link function gets the HTML element (iElement) as parameter. We only have to call the mobiscroll init.

Inside the link function the iAttrs parameter holds all the attributes the element has. The calendar attribute (iAttrs["calendar"]) will hold the scope variable the component should be bound to. The parse service will actually parse the expression and return a function. If the expression is assignable it will have an assign function. Here its name is setter, and calling it will set the variable. The mobiscroll calendar has different methods to get the value based on the multiselect option. As you can see in the handler, we have to check that option first and get the value accordingly.

Another notable thing is that all the logic is wrapped around the $apply function. This is required for angular, to get notified about the changes made inside the function.

The next step is to notify the calendar if the variable changes. For this, we use the controller function and the scopes $watch function. This way we can register a listener to be executed when our variable changes:

The first function returns the value that should be watched. The second function gets called when the value changes. Here we also have to distinguish between the multiselect and single select modes of the mobiscroll calendar. The last parameter is a boolean, which tells angular to compare objects for equality rather than for reference.

Here we used the $eval function to create the mobiscroll initialization object. The $eval uses the parse service that we mentioned earlier and evaluates the expression on the current scope. This way we can pass the mobiscroll options in the mobiscroll-options attribute like this:

Mobiscroll event handlers are functions that you pass. So where are these functions defined?
When we pass a setting like onSelect, Angular treats it just as any other properties. It evaluates it against the current scope. This means when we define a function in the current scope we can pass it as an event handler to mobiscroll.

However there is a small detail you should be aware of. When the mobiscroll event handlers are called, they are outside of the Angular world. If we change a scope variable inside a handler like this, Angular will not be notified about it and the change will not propagate. To overcome this the simplest solution is to put the event handler inside an $apply() function.

For more info on our AngularJS integration plugins please see our documentation.
This is the main idea behind the Mobiscroll AngularJS Integration. Let us know how and what do you plan to integrate next?

Did we leave something out, do you have anything to add, comment? Please let us know in the comment section below!

Start building better products

Sign up and get posts like this in your inbox. We respect your time and will send you only the good stuff!