Dart #8: homepage part 2

Today we continue with the homepage for Teamoji. In the last tutorial we finished the main content of Homepage. But we are still missing the hidden menu part on the left. This introduces a new concept of Angular Dart: deferred content. So without further ado, let’s jump in!

Homepage_drawer.png
Mock

What’s Deferred Content?

Before we dive in code it is important to understand the modal component and deferred content. Deferred content roots from the Lazy Evaluation Principle:

“Lazy Evaluation, or call-by-need is an evaluation strategy which delays the evaluation of an expression until its value is needed.”

You might think: how is lazy a good thing? Consider the following scenario: the user logs into the homepage, which displays the recent chat history of a particular team. The user is very active in this team, and rarely switches to other teams.

Without lazy evaluation, we will compile and load all components when user accesses the page. However the user never expands the left menu, making the load time for that component virtually useless. On the other hand, with lazy evaluation, we choose not to compile and load the hidden components, and only load them when user is asking for them. This way we speed up the initial page load, which is crucial to acquisition and retention.

lazyness

The menu component

We can see the bits of the menu component quite clearly from the mock:

  • A header that says “Your teams”.
  • A list of the teams the user belongs to, highlight the one currently on display. (ngFor)
  • A button to create new Team. (Material-button)
  • A sign out button. (Material-button)

At this point you should be fairly comfortable with all these techniques. The only thing to watch for in the Application Layout format.

<material-drawer temporary #drawer="drawer"
[attr.overlay]="true">
<div class="tm-home-drawer">
<div class="tm-home-drawer-header-row">
{{drawerHeaderMessage}}
</div>
<material-list class="tm-home-drawer-list">
<material-list-item *ngFor="let team of teams"
class="tm-team-list-item"
[class.deep-blue]="shouldShowAsDeepBlue(team)"
(trigger)="onChangeTeam(team)">
{{team}}
</material-list-item>
</material-list>
<div class="tm-home-drawer-btns">

{{createTeamButtonMessage}}


{{signOutButtonMessage}}

</div>
</div>
</material-drawer>

There are a few points to note. First notice we name the material-drawer as drawer. This is so that we can toggle it by clicking on the menu button on the homepage:

<material-button class="material-drawer-button" icon (trigger)="drawer.toggle()">
<material-icon icon="menu"></material-icon>
</material-button>

Also notice the *deferredContent marker in the fist div. The * has the same meaning as in *ngFor: this is a structural directive, which alters the DOM tree. Adding this marker tells the dart engine: don’t load me unless needed. The rest is fairly standard stuff.

After adding this into the homepage, we can see something like this:

Screen Shot 2018-01-07 at 22.29.41

Conclusion

At this point we have technically finished all mocks given in the first place. But as you can probably see, this app is still broken. There are some functionalities missing, such as a button to join a team. Also there’s no navigation between the pages. In the next post we will address these problems, and get started with firebase!

As usual if you get stuck somewhere, always feel free to checkout the repo, or PM me the specific issue. Happy coding!

Advertisements

Dart #7: Homepage part 1

Hello there! Sorry I have been away for a few weeks due to uni work and other stuff, but today we will start working on the homepage of Teamoji, which will be the last page left, before we start hooking up everything and starting with Firebase!

As I mentioned before, due to the complexity of the app, we will split this page into a few posts. In this post we will work on the main content, which consists a header, a list of recent posts, and a button to post new emoji.

Homepage
Our goal today

UserPostComponent

At this point, you should have a bit of an “Angular” senses about how to implement things, given Angular’s features and principles. It is not hard to see we would want a component for one post by a user, and in the main component we would simply *ngFor a bunch of this sub-component.

So let’s build that.

First you should consider what exactly this UserPostComponent should do. It should display a posted emoji by a user. From that, we see there are actually two things needed for this component to display:

  • a User who posted this emoji.
  • What emoji it is.

As a result, we would want to have 2 @Input() bindings from upstream, and that’s exactly what we will do.

user_post.dart

import 'package:Teamoji_tutorial/src/emoji_render/emoji_render.dart';
import 'package:angular/angular.dart';

@Component(
selector: 'user-post',
templateUrl: 'user_post.html',
styleUrls: const ['user_post.css'],
directives: const [
EmojiRenderComponent,
],
)
class UserPostComponent {
@Input()
String emoji;

@Input()
String userName;

String get shortUserName => userName.trim().toUpperCase().substring(0, 1);
}

user_post.html

<div>
<div class="tm-user-post-user-icon">
<div class="tm-user-profile-image">{{shortUserName}}</div>
</div>
<emoji-render [useBigIcon]="true" [icon]="emoji"></emoji-render>
<div class="tm-user-post-timestamp">1h</div>
</div>

user_post.css

.tm-user-profile-image {
border-radius: 50%;
height: 30px;
width: 30px;
background-color: dodgerblue;
color: white;
display: table-cell;
text-align: center;
vertical-align: middle;
}

.tm-user-post-timestamp {
text-align: right;
color: lightgray;
}

I won’t go into detail about how this component is built. Everything should be fairly easy to grasp. There’s one bit that requires some thinking though, which is rounding the div for shortUserName but still make the text centered. The last three lines in .tm-user-profile-image realize that. Take a second look and really understand the reason for each line.

Another thing worth mentioning is that tapping on a recent post doesn’t do anything, hence no @Output() event needed.

Screen Shot 2017-10-20 at 23.40.08
I am cool kid!

Main homepage content

Now that we have UserPostComponent, it is finally time to start building our homepage.

As we considered before, for now the homepage will have 3 main components:

  • a header.
  • a list of UserPostComponent.
  • a button to post new emoji.

Let’s double check if we have everything needed. The header will be an “icon button” plus some text, this is easy. The main section is a list of posts, which we have as well(for now we will mock a list of emojis, but eventually this should be pulled from Firebase). And last the button to add new emoji. There’s actually a designated name for this sort of button on the lower right side on page, according to Angular Material Design: Floating Action Button, which we can just use out of the box. So we have everything we need, let’s build it.

homepage.html

<div class="tm-main-content">
<div class="tm-main-content-header-row">



<div class="tm-main-content-header-title">Header</div>
</div>
<div class="tm-main-content-content">
<ul style="padding-left:0;">
<li class="tm-prev-emoji-item">

</li>
</ul>
</div>
<material-fab class="tm-add-post-icon" aria-label="add" raised (trigger)="onAddPost()">
<material-icon icon="add" size="x-large"></material-icon>
</material-fab>
</div>

homepage.dart

import 'dart:async';
import 'package:Teamoji_tutorial/src/common/messages.dart';
import 'package:Teamoji_tutorial/src/create_team/create_team.dart';
import 'package:Teamoji_tutorial/src/services/firebase_service.dart';
import 'package:Teamoji_tutorial/src/user_post/user_post.dart';
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';

enum ShowingComponent {
homepage, create_team, emoji_selector,
}

@Component(
selector: 'homepage',
directives: const [
MaterialButtonComponent,
MaterialFabComponent,
MaterialIconComponent,
MaterialListComponent,
MaterialListItemComponent,
NgFor,
UserPostComponent,
],
templateUrl: 'homepage.html',
styleUrls: const [
'homepage.css',
])
class HomepageComponent extends HomepageMessages{
List<String> _mockEmojiList = const [
'\u{1F60B}',
'\u{1F60E}',
'\u{1F60D}',
'\u{1F618}',
'\u{1F617}',
'\u{1F619}',
'\u{1F60B}',
'\u{1F60E}',
'\u{1F60D}',
'\u{1F618}',
'\u{1F617}',
'\u{1F619}',
'\u{1F60B}',
'\u{1F60E}',
'\u{1F60D}',
'\u{1F618}',
'\u{1F617}',
'\u{1F619}',
];

List<String> get previousEmojis => _mockEmojiList;

void onAddPost() => print('should show select emoji component');
}

At first let’s do zero css and see what we got.

Screen Shot 2017-10-20 at 23.12.43
Yeah… You gotta make a bit more sense than that.

In the next section let’s work carefully with css and the page more like a page.

CSS homepage

In this section I won’t go too deep into stuff like font and color. We are going to focus mainly on layout.

First let’s make the root div stretch to full screen, adjust the background color too.

.tm-main-content {
background: lightyellow;
height: 100%;
width: 100%;
}

This won’t change any layout. Our next goal is to make the header text and the button in one row, and use a different background color to mark the header part. There are many ways to do that, but ultimately we need to change the display attribute for the header top-level div. By default it is set to block, which just stacks child elements vertically. Hence the above picture.

.tm-main-content-header-row {
background-color: orange;
display: flex;
}

.tm-main-content-header-title {
padding: 10px 5px 0 0;
}

This fixes the header div for us. It is worth noting you want to have some padding for the text, otherwise it would touch the button at the upper bound since it is set to flex.

Screen Shot 2017-10-20 at 23.26.21
A bit better now.

Now let’s fix the user post list. The problem is the same as the header: display attribute. Here we want to have the posts stacked up, but use horizontal spaces too, this is done by setting it to inline-block.

.tm-main-content-content {
height: 100%;
padding: 8px;
}

.tm-prev-emoji-item {
display: inline-block;
padding: 0 20px;
}
Screen Shot 2017-10-20 at 23.34.09
So close… Just missing the button now.

And lastly the FAB. Here we are just going to fix the position at the lower right corner of the page, even when scrolling.

.tm-add-post-icon {
color: white;
background-color: deepskyblue;
position: fixed;
right: 12px;
bottom: 12px;
}

After that, we should have the homepage nice and pretty.

Screen Shot 2017-10-20 at 23.34.32.png
Nice and pretty indeed 😀

Conclusion

Let’s recap what we did today. We created a sub component to display a post from earlier, and we have the main content of the homepage done. The most challenging part maybe playing with CSS, you might find this and this to be helpful in understanding display.

As usual, let me know if anything is unclear. Happy building!

Dart #6: Emoji selection

After the create team page, this week we are going to be building the emoji selection page. As usual the code I present here is somewhat partial, so let me know if anything is unclear.

emoji_selection
Our mock

How to build it?

As mentioned in last week’s post, we are going to leverage EmojiRenderComponent to build this component, and it is not hard to see why. Every little emoji to select is an EmojiRenderComponent. If we have a list of emoji unicodes, then a simple material-list should do.

So the question becomes: where do we find all the emoji unicodes? Answer is, and usually will be, our good friend Google. A simple search would turn up some csv file, and with a little python formatting, we are good to go.

One thing worth pointing out though is current I am putting the entire list as a private variable in the component, and ideally it should be fetched from some service. We will address this when we get to Firebase.

Now let’s take a look at the code.

emoji_selector.dart

import 'package:Teamoji_tutorial/src/common/messages.dart';
import 'package:Teamoji_tutorial/src/emoji_render/emoji_render.dart';
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';

@Component(
selector: 'emoji-selector',
templateUrl: 'emoji_selector.html',
directives: const [
EmojiRenderComponent,
MaterialIconComponent,
MaterialButtonComponent,
NgFor,
],
styleUrls: const ['emoji_selector.css'],
)
class EmojiSelectorComponent extends EmojiSelectorMessages with EmojiList {

void onCancel() => _dismiss();

void onSelect(String emoji) {
print('You want to post $emoji');
_dismiss();
}

void _dismiss() => print('You want to cancel selecting an emoji');
}

This is pretty straightforward. I am printing out the actions instead of actually implementing them. This simplifies the component for now, and we can fill these up when we put everything together.

emoji_selector.html

<div class="tm-emoji-select-header">
<div class="tm-emoji-select-header-message">{{promptSelectMessage}}</div>
<material-button class="tm-emoji-select-header-button" icon (trigger)="onCancel()">
<material-icon icon="clear"></material-icon>
</material-button>
</div>
<div class="tm-emoji-select-content">
<ul class="tm-emoji-select-list">
<li class="tm-emoji-select-item">

</li>
</ul>
</div>

Note we use a combination of material-button and material-icon to realize the cancel button. There might be cleaner ways to implement this, but as far as I know this is the conventional way.

Also interestingly there’s an * before the ngFor, that’s because ngFor is a Structural Directive. This asterisk is saying “I will potentially alter the DOM tree, so parse me a bit differently”. In our case, because we are enumerating a list, whose length is unbeknownst to the template, it can potentially grow to many lis, thus altering the DOM tree.

I won’t show the CSS here, it is in the repo if you to take a look. Also I am pretty sure I did a lot of hacky stuff there, so you might want to implement the layout and styling by you own.

Screen Shot 2017-09-24 at 16.36.07
Final render. Also the selection “works” too!

Once we have this component done, the only component left is the homepage component. Unfortunately this is the most complicated component to implement, so we will split into 2 or 3 posts for that.

Let me know if anything can be improved. Thanks for reading, and I will see you all next week.

Dartlang #5: Create Team

Today we continue with our Teamoji web app. My apologies for putting this off for so long, everything has been a bit crazy because of the moving. Now that I am done with that, the series will pick up as usual. In this post we focus on 2 components: EmojiRenderComponent and CreateTeamComponent. All the code can be found in our Github repo; you will also notice there are some new component there which I haven’t talked about. We will cover them in the upcoming few posts, no worries. So without further ado, let’s get started.

EmojiRenderComponent

You may realize that there is not any particular page that this matches to. That’s because this component will be a sub-component for many other components. Think about the big fox emoji we have in the welcome page. If we take a look at the create team page, it also has a big emoji on the page.

Screen Shot 2017-09-14 at 16.18.03

Screen Shot 2017-09-14 at 15.23.18

Can we somehow just have one component that simply shows a configureable emoji? Since Angular Dart is component based, we should be able to reuse this common component every time we need to show an emoji. It’s very clear that having an EmojiRenderComponent avoids duplicate code and helps a lot with readability and maintainability.

So how do we go about building such a component? Turns out it is almost too simple, with the @Input() from Angular. Let’s take a look at the code first, and I will explain it.

emoji_render.dart

import 'package:angular/angular.dart';

@Component(
  selector: 'emoji-render',
  templateUrl: 'emoji_render.html',
  directives: const [
    NgStyle,
  ],
)
class EmojiRenderComponent {
  @Input()
  bool useBigIcon;

  @Input()
  String icon;
}

emoji_render.html

<div>
{{icon}}
</div>

First let’s look at the @Input() thing. There’s a detailed doc on Angular Dart official site, but essentially think of components like a tree. For the parent to pass something to its child component, the child must declare an input to be assigned. Conversely, when the child wants to propagate something to the parent, usually an event, it must declare an output. We have used the input here, but we will see the output being used in other components soon.

parent-child-binding

Also an interesting feature of Angular is shown here too: NgStyle. Normally if we want to set some style dynamically to a div, we assign different classes to it on the fly. This in my opinion is unnecessary and ugly, since you end up with class names like blue-btn, which is just to generic, and if you have to switch a button from blue to red on the fly, you have to remember to remove the blue-btn class, otherwise sometimes the button will stay as blue.

In Angular, after including the NgStyle directive, we can define a specific style to be evaluated from a dart expression. Here the font-size is controlled by the Boolean variable useBigIcon. Incidentally, this variable is also an input, which means the parent can decide either to show a big emoji, or a small one. Flexible.

After this is created, we can replace the emoji template in WelcomeComponent with the following. You would also need to include EmojiRenderComponent in the directive list for this to work.

- <div class="tm-app-icon">{{appIcon}}</div>
+ <emoji-render [useBigIcon]="true" [icon]="appIcon"></emoji-render>

This may seem like a small change, but I think it is very important to have modularity in your codebase.

CreateTeamComponent

Ok now that we have the building blocks, let’s actually build the component for creating teams. This is pretty trivial, since the overall structure will be the same with our existing WelcomeComponent. Take a look(no css here but you can find it in the repo):

create_team.dart

import 'dart:async';
import 'package:Teamoji_tutorial/src/common/messages.dart';
import 'package:Teamoji_tutorial/src/emoji_render/emoji_render.dart';
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';

@Component(
  selector: 'create-team',
  templateUrl: 'create_team.html',
  styleUrls: const ['create_team.css'],
  directives: const [
    EmojiRenderComponent,
    MaterialButtonComponent,
    MaterialInputComponent,
  ],
)
class CreateTeamComponent extends CreateTeamMessages {
  String newTeamName = null;

  Future<Null> create() async {
    print('You want to create a new team called: $newTeamName');
    newTeamName = '';
  }
}

create_team.html

<div class="tm-create-team">

<div class="tm-prompt-header">{{createTeamPromptHeader}}</div>
<div class="tm-prompt-content">{{createTeamPromptContent}}</div>
<material-input
floatingLabel
label="Name of your new team"
name="text"
(change)="newTeamName = $event">
</material-input>
<material-button
raised
class="tm-btn"
(trigger)="create()">
{{createTeamButtonMessage}}
</material-button>
</div>

You can see we are re-using EmojiRenderComponent here too, which was the reason we built that in the first place.

Here the interesting thing to look at is “. You will notice there’s an “attribute” we associate with this tag: (change)="newTeamName = $event". This is the output event binding we glossed over earlier.

Consider you are the input box yourself. You have the user’s input, but you yourself can’t make much out of it since you are just a generic input, and you have no idea what the user’s input is about. It could be a name, an email address, etc. However, your parent would probably know what that’s for and can take care of the input. As a result, you pass your input value upstream as an event. Here change is the name of the event, meaning the input value has changed, and the parent’s action to that is to assign the newest input value to a variable.

You might be wondering: ok that’s very cool, but how would I know what event these material components are emitting, and what type of parameter are associated with it? You can find detailed documentation about these components in the AngularDart Material component repo. In our case it’s the material input.

Once you have these all understood and in your project directory, change your AppComponent to show CreateTeamComponent and run pub serve.

Screen Shot 2017-09-14 at 16.20.27

Conclusion

In this post we are getting into the Angular world, with input/output binding, and more practice with material components. Most importantly, it is of great importance that we stick to the basic software engineering principles, in this case modularity. In the next post we will continue to build all the components we need and once we have all the components we need, we can start integrating Firebase in.

Hope you enjoyed this. Let me know if anything is unclear or can be improved.

Dartlang #4: Welcome page

Today we are actually going to code something finally. As a good starter, we will build the welcome page, which is what users see when they first got to the website.

Welcome
Our mock

Note: if you like to follow along the tutorial, make sure you pull from this commit as this will be our starting point onward. Also, basic dart syntax and AngularDart architecture are assumed, if you are not sure about them, check out AngularDart’s official site.

Step 1: got the content up

Before we get into placement and styling, the first thing is to have some content to show obviously. So in the current app, remove todo/ directory, since we are not building a TODO list. Instead, add a package named welcome, create a component as WelcomePageComponent(with blank html and css for now), and configure AppComponent to point to that.

// app_component.dart

@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html',
  directives: const [materialDirectives, WelcomePageComponent],
  providers: const [materialProviders],
)
class AppComponent {
}
//app_component.html

<welcome-page></welcome-page>

 

This is basically saying “now my app component is just the welcome page component”, which is fine for now. We will first build individual pages, and then worry about routing and redirections.

In welcome_page.dart, add the content according to the mocks, and then just place them in divs in welcome_page.html.

// welcome_page.dart

import 'dart:async';
import 'package:angular2/angular2.dart';
import 'package:angular_components/angular_components.dart';

@Component(
  selector: 'welcome-page',
  templateUrl: 'welcome_page.html',
  styleUrls: const ['welcome_page.css'],
  directives: const [
    MaterialButtonComponent,
  ],
)
class WelcomePageComponent {
  String get appTitle => 'Teamoji';

  String get appSubtitle => '\u{1F551} Team Status \u{1F680}';

  String get appIcon => '\u{1F63B}';

  String get signInMessage => 'sign in with google';

  String get appMainFooter => 'Powered by Firebase';

  String get appSubFooter => 'source on github';

  Future<Null> login() async {
    print('Login not implemented yet');
  }

}

For the emojis, I used standard Unicode to show them. You can find a complete list of emojis and their corresponding Unicode encoding here. This will be important when we implement the emoji selection page.

<div class="tm-welcome">
    <div class="tm-app-icon">{{appIcon}}</div>
    <div class="tm-main-header">{{appTitle}}</div>
    <div class="tm-sub-header">{{appSubtitle}}</div>
    <material-button raised class="tm-login-btn" (trigger)="login()">{{signInMessage}}</material-button>
    <div class="tm-main-footer">{{appMainFooter}}</div>
    <div class="tm-sub-footer">{{appSubFooter}}</div>
</div>

For now you can safely ignore the classes assigned, we will use them for styling later. One thing worth noting is that face that we are not using a regular for the login button, but a. This is the main package for our project since material design looks better and has many built-in functionalities handy. Check out this site for more detail on AngularDart material components.

After all these work, run pub get and pub serve on the command line, then load the page on localhost. You should see something like this:

Screen Shot 2017-06-25 at 17.36.06

Step 2: Add styling

So we have all the content on the page, that’s 50% done! Next is to make the content look like the mock. Starting from the easy bits, these are what we can do.

Environmental styling

These are stylings that should affect most tags, so they should go into styles.css under web/:

html, body {
    height: 100%;
    width: 100%;
}

body {
    margin: 0;
    background-color: deepskyblue;
}

Here we make the component to fill the page, and have a light blue background color.

Tag specific styling

Here we make specific changes to each tag, using the classes we set earlier. These include font size, color, padding, etc. I won’t go into too much detail, but here is the code:

:host {
    font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
    color: white;
}

.tm-welcome {
    height: 100%;
    text-align: center;
}

.tm-app-icon {
    font-size: 125px;
}

.tm-main-header {
    font-size: 40px;
}

.tm-sub-header {
    padding: 0 0 20px;
    font-size: 16px;
}

.tm-login-btn {
    background-color: dodgerblue;
    margin: 20px 0;
}

.tm-main-footer {
    font-size: 12px;
    padding: 5px 0 10px;
}

.tm-sub-footer {
    color: lightgrey;
    font-size: 10px;
}

After these changes, the page should look like this:

Screen Shot 2017-06-25 at 17.51.56

Placement

This in my opinion is the hardest part. What we want is to have the top level div centered both horizontally and vertically. Let’s see the code first:

.tm-welcome {
    height: 100%;
    justify-content: center;
    align-items: center;
    display: flex;
    flex-direction: column;
    text-align: center;
}

The first 4 lines make the div centered on page, but the children divs are horizontally aligned. To change this, adding flex-direction: column; would line those children vertically. To be honest, CSS is kind of hard to make work, and you need to use trial and error to get what you want.

Conclusion

If everything works good, you will see our page now looks almost close to the mocks.

Screen Shot 2017-06-25 at 18.18.33

Screen Shot 2017-06-25 at 18.25.31
Looks good in mobile as well 😀

Let me know if there’s something confusing in this tutorial, and I will fix it and keep that in mind as we go on. This week we will build the “Create team” page, which is also quite simple, but we will see another material component. Stay tuned!

Dartlang #3: Teamoji starts!

After the previous two posts, we are finally set to start actually building something in AngularDart! As I mentioned before, the app we are building for this series is called Teamoji, which was shown in Google I/O 2016.

In the video I linked above, the basic app is there, and the presenter adds extra functionalities to better UX and eventually Teamoji become a Progressive Web App. In this series we are only interested in building the basic app, and those extra functionalities might come as stretch goals for later.

Nevertheless, we might know what to build before building it, so in this post we want to quickly outline the things we are building, both for front end and back end, and more importantly, the strategy we will use to build the app from literally nothing. I understand my development methodology is probably flawed, and there are definitely a great many other ways to do it, so any suggestion and comments are very welcome. So without further ado, here we go!

What is Teamoji

Before I go into specs and designs, let’s at least have some idea what it is functionally speaking. Think of this app just a group chat, where you create and join groups and post messages that everyone in the same group can see. The only catch is those messages will not be text, but emoji.

teamoji

Backend

The reason I started with back end is that in our case, building back end will be relatively easy to do. There are three main things to handle in the backend:

  • Login
  • Storage for messages
  • Storage for user and group info

Fortunately there are not really any business logic to be implemented, and all we need is to get a login call, and DB schema for user info, group layout, and chat log.

So how do we go about and implement them? If it was me 6 months ago, I’d say setup a MySQL database and define schema, build a ORM layer, write some PHPs, and just call them from the front end. This could take weeks all by itself. Fortunately for this project we can speed things along a little bit, by using Firebase, a framework from Google that gives easy setup for database, and login methods for Google, Facebook, etc. Also, it has a realtime database, whose schema is in JSON and can be easily changed. This fits our use case perfectly, so we will be using that for most of our backend stuff, although honestly it is not really a backend anymore, since we won’t be writing a single line of backend code.

Frontend

This is the main focus of the project, where I plan to practice the most of AngularDart. We will need essentially 4 pages for this app:

  • Startup page
  • Login page
  • Home page
  • Emoji selection page

I have included screenshot of all these pages in the repo, which can be found at the end of this post. Right now these is only the template code generated by the framework, but over the coming weeks we are going to replace it with our own code.

If you remember the first post of the series, the first thing we know about Dart is everything is a component. So what we will do for UI is we will break down each page as many small components and build them one by one. In the end, we put them together to form each page, and then add routing to make the whole app coming into life!

What’s coming

This will be our Github repo for this series. As you can see I am developing this real time, and I have no idea what’s to come either. But I am sure this will be a valuable journey, and hope you will like it too.

This weekend we will start by building the UI for the Startup page, which is the easiest to build, but will be a great step to get your feet wet with AngularDart. I plan to post it on Sunday, so stay tuned for that!

Dartlang #2: Dependency Injection

Welcome back! The first post turned out to be the most viewed post on this site, I am so grateful and motivated to keep this going. So here we go, dependency injection!

what-is-dependency-injection

What is it?

In first glance, the phase sounds fancy and sort of hard to grasp, so I have laid out a route to make this easier.

What’s a dependency?

This part should be relatively easy to grasp. Say you are a carpenter, and you need a chisel to make a sculpture, then it can be said that you have a “dependency” on the chisel.
Moving back to a web programming context. A simple example would be a front end event handler needs some database object to fetch user data, then the handler has a dependency on the database object. So far so good?

What’s injection?

Now that we have the notion of dependency clear, let’s think about how we usually establish them. The easiest way is to have it as a property and instantiate a new object in constructor, such as:

class Carpenter {

    // Dependent object
    private Chisel chisel;
    
    public Carpenter() {
        chisel = new Chisel();
    }

    void makeSculpture() {
    
        ...
        
        // Use the dependency
        this.chisel.apply();
    
    }
    
}

Now this code has no dependency injection, because the dependency is actually established by the object that holds the dependency. What if the dependency object, aka the chisel, is given to you somehow when you are constructing the Carpenter object? In other words, what if your constructor looks like this:

public Carpenter(Chisel chisel) {
    this.chisel = chisel;
}

This way the dependency object is supplied by some other party, and we can say those party injects the dependency into Carpenter. This is essentially what dependency injection is.

Why bother?

Let’s take a look back at what we did. We changed chisel = new Chisel(); in the constructor into a parameter, and we would need some third party to inject this when we instantiate a new Carpenter. Sounds kind of overly complex right? Well it turns out there are a few good reasons why.

Flexibility

There’s one important principle what drives the creation of dependency injection, called the Dependency Inversion Principle. What it states basically is you want to depend on abstractions, not specific classes. Imagine the Chisel in the example above is an interface, then the injecting party can supply any kind of chisel to a carpenter, each for different job, without changing any code in Carpenter.
This is sometimes referred to as “loose coupling”, and it gives Carpenter flexibility in its behaviors, without needing to modify the class itself.

Modularity

Since we can extract implementation from interface, we are inherently given more modularity. This is an obvious point, but nevertheless important in software engineering.

Testability

Dependency injection can also help testing. You can basically inject different implementations to the same object, and test its behavior. No need to write tests like testWoodChiselWorks() and testStoneChiselWorks(), which will have 80% code exactly the same. Simply compose a map of implementations to their expected  behaviors and loop it though in one fixed test framework. Ezpz.

DI in action: AngularDart

So far we know what dependency injection is, and why it is a good pattern to use, but there are still two problems: a) how to use them, in AngularDart specifically, and b) what about this third party object that’s responsible for all the injecting? In this section we will see how DI is used usually, and why injecting thing is not a worry.

Standard DI model

Let’s take a look at an example from the official site:

// Dependency object
import 'package:angular2/angular2.dart';

import 'hero.dart';
import 'mock_heroes.dart';

@Injectable()
class HeroService {
  List<Hero> getHeroes() => HEROES;
}

Notice a special annotation before the class declaration: @Injectable(). This marks the class as something to be injected with. In terms of how exactly it is injected, we will talk about it in a bit.

// Dependent object
import 'package:angular2/angular2.dart';
import 'hero.dart';
import 'hero_service.dart';
@Component(
  selector: 'hero-list',
  template: '<div>{{hero.id}} - {{hero.name}}</div>
'
,
  directives: const [CORE_DIRECTIVES],
  providers: const [HeroService],
)
class HeroListComponent {
  final List<Hero> heroes;
  HeroListComponent(HeroService heroService) : heroes = heroService.getHeroes();
}

We see clearly the HeroService is to be injected as a parameter in the constructor, exactly the same in our Carpenter example.
Ok so let’s address the problem: who does the injecting? The answer is nobody, in a sense. As a programmer, you won’t need to write a single line of code to do the injection, it is done for you by dart automatically.
You may say “that’s very cool for dart, but how does it know what to inject into what?” This is where the @Injectable() comes to play. If a class has this annotation, it tells the dart VM that “I am an injectable thing, feel free to plug me in if someone needs me.” There’s a question about the injectable itself too, how is it instantiated? Normal new method, factory, or singleton? Turns out you can choose either one. For the sake of understanding I will not go into too much detail about this, but you can read about it online easily.
Ok so we settled the first bit, now where to inject into? There are two signs a class can tell the VM to inject something into itself. One is by listing it in the constructor, and the other is in the metadata. Note the line that says providers: const [HeroService],. This is saying “I need this HeroSerive thing injected for me” loud and clear. This the VM knows to inject it into the component, and in the component you just use it normally. Magical.

Conclusion

So that is dependency injection. As I mentioned earlier we won’t be using this too much in our project, since we don’t really need a backend and we can just fetch directly from the database.
In case this post doesn’t do it job, here are some more resources to help: