Silverlight to Angular – 5 (IValueConverter – filter)

IValueConverter is without doubt one of the most used feature (at least in our side of the world) in Silverlight. We have lot of data, which, if we show them as it is to the user, it is completely useless. To make it more meaningful, we use Value Converter to convert and display it to the user. IValueConvert provides a way to add logic to the binding data without changing the data. IValueConverter has two methods, ‘Convert’ to convert the original data that is bound but translate with some logic to give different result that then get rendered in the UI. ‘ConvertBack’ is to take user input and apply some logic to revert it to some other form to store it at the back end. Most of the time, whenever we use IValueConverter, we always end up using the ‘Convert’ and seldom use ‘ConvertBack’, now I am going to use that as an excuse since Angular provides only one way convert, it does not have provision to convert it back. Even though I say, we don’t use ‘convertback’ but it is very useful feature and is used a lot, one good example is ‘Color Picker’. We will try to explore convert back at a later time. For now, we will see what is available in Angular out of the box that we can use.

Problem: Multiply two numbers and display the result with two decimal points.

Silverlight:

Only difference between our previous solution to this is that we have value converter and it is used in the binding to change the incoming data to more meaningful data. Lets look at the view

View:

1 <Grid.Resources> 2 <converter:TwoDigitConverter x:Key="Converter" /> 3 </Grid.Resources> 4 <TextBlock>Number 1</TextBlock> 5 <TextBox Text="{Binding NumberOne, Mode=TwoWay}" Grid.Column="1"></TextBox> 6 <TextBlock Grid.Row="1">Number 2</TextBlock> 7 <TextBox Text="{Binding NumberTwo, Mode=TwoWay}" Grid.Row="1" Grid.Column="1"></TextBox> 8 <Button Grid.Row="1" Grid.Column="2" Command="{Binding Multiply}" CommandParameter="">Multiply</Button> 9 <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Total, Converter={StaticResource Converter}}"></TextBlock>

Line (2 – 4) provides us the hook into the value converter to be used in the XAML. Line (9) binds the result, even though the it binds to the result, we are asking the binding to use the associated converter to apply the conversion based on the convert logic and use the result to display in the ‘TextBlock’.

ValueConverter:

1 public class TwoDigitConverter:IValueConverter 2 { 3 4 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 5 { 6 var result = value as float?; 7 result = result ?? 0; 8 return string.Format("{0:N2}", result); 9 } 10 11 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 12 { 13 throw new NotImplementedException(); 14 } 15 }

When we create Value Converter, it has to implement IValueConverter, which have only two methods that we need to implement. Convert and ConvertBack as we discussed in the beginning. Since Angular only supports one way conversion, we created this sample conveniently to show case only the ‘Convert’ part of ValueConverter.  Convert method does not do anything special, it takes the input number and returns the result with 2 decimal digits.

Our view model exposes the three variables and a command, nothing else.

Angular:

Angular provides filters, a way to format data for display. There are couple of ways we can use filters. You can use filters in line or create custom filters. If you were to create custom filters, you can reuse them in any controllers in a given module, it is like using resource file in Silverlight. One additional benefit of the creating custom filters, you can chain them to pass the input to multiple functions before creating final result. Lets first look at the inline approach to solve the problem and then we will write custom filter.

In-Line formatting:

View:

Since it is inline formatting, the formatting happens in the View code itself.

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 6 <script src="scripts/controller.js"></script> 7 </head> 8 <body> 9 <div ng-controller="controller"> 10 First Number: <input ng-model="NumberOne"/><br/> 11 Second Number: <input ng-model="NumberTwo"/><button ng-click="Multiply()">Multiply</button><br/> 12 Result : {{Result | number:2}} 13 </div> 14 </body> 15 </html>

Everything is standard here except line (12). In line 12, we get the result from the controller and angular will read the result and feed it to the expression in the pipe. In this case we are using number filter out of box to format number. There are few filters available out of box,  take a look at this AngularJS cheat sheet.

Custom formatting:

There are situations, where out of the box filters will not be sufficient and we will need some custom filters to format the data. Angular filters are very powerful on that regard. As I said previously,

  1. Since you can create filters as part of module, these filters are available across all the controllers in the module.
  2. Filters can be chained to create more customizable output data.
  3. Compare to Silverlight, we can pass in as many parameters as you want to the filters.
  4. If the filters are very simple and out of box, use the default filters.
  5. It written properly, you can call filters with only available arguments and rest can assume default values(like optional parameters in c#).

So in our case, even though we could use simple out of the box formatting, we will create a custom filter just for the sake of demonstration. So far in all our examples we left ng-app as empty string but when you want to use filters then you need to create a module and assign the filter to that module. With that in mind, here is the modified view.

1 <!DOCTYPE html> 2 <html ng-app='customFilters'> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="controller"> 8 First Number: <input ng-model="NumberOne"/><br/> 9 Second Number: <input ng-model="NumberTwo"/><button ng-click="Multiply()">Multiply</button><br/> 10 Result : {{Result | twoDigits}} 11 </div> 12 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 13 <script src="scripts/controller.js"></script> 14 </body> 15 </html>

Line (2) now has the module name. We named it as ‘customFilters’. You will see in the view model, how we create a module and add the filters into the module.

**Note: It important that you put the module name in ng-app, if not none of the custom filters you write will work. Take it from me, I spend hours trying to figure out why my custom filter was not working, finally to find out, I missed the module name in the ng-app. **

Line (10) now feeds the result value to the custom filter ‘twoDigits’, which will do the magic of converting the result to a number with two decimal digits.

Controller:

1 angular.module('customFilters', []). 2 filter('twoDigits', function() { 3 return function(input) { 4 return input.toFixed(2); 5 }; 6 }); 7 8 function controller($scope) { 9 $scope.NumberOne = 0; 10 $scope.NumberTwo = 0; 11 $scope.Result = 0; 12 $scope.Multiply = function () { 13 $scope.Result = $scope.NumberOne * $scope.NumberTwo; 14 }; 15 }

So what is new compare to what we have seen so far?  Line (1-6) creates the module and adds the custom filter to the module.

Line (1) – creates the module named ‘customFilters’. During the angular context generation, angular get hold of ng-app for the first time, it will look for the definition of module in the controller to bootstraps the application. In the module definition, there are two parameters, first one is the name of the module and for sake of simplicity, lets ignore the second parameter ‘[]’ for now.

Line (2) – Please note that, there is a ‘.’ at the end of the line (1), with that we are directly adding a filter called ‘twoDigits’ to the filter factory.

Line (3) – Actual function which takes input and perform some task, in here format number to two decimal digits (line 4) and return the result.

Even though I presented ‘filters’ as way to format data, it is much more than that, it can do what ‘filter’ is supposed to do like filtering. We will look at that in one of the later post. Lets take this example one more level up to show how to pass parameters to the filter.

Problem: Two two number and multiple and set the result precession based on user input.

View:

The view is exactly same as the last one except now, we have one input field to enter number of decimal digits user wants to see in the result.

1 <div ng:app="customFilters"> 2 <div ng-controller="filterCntl"> 3 First Number: <input ng-model='NumberOne'></input><br> 4 Second Number: <input ng-model='NumberTwo'></input><button ng-click='Multiply()'>Multiply</button> 5 Decimals : <input ng-model='Decimals'></input><br> 6 Result: {{ Result | twoDigits: Decimals }} 7 </div> 8 </div>

The interesting part in the view is Line (6), this time, instead of feeding result to twoDigit filter, we are also passing the Decimals value as parameter to the filter.

Controller:

1 angular.module('customFilters', []). 2 filter('twoDigits', function() { 3 return function(input, decimals) { 4 return input.toFixed(decimals); 5 }; 6 }); 7 function filterCntl($scope) { 8 $scope.NumberOne = 0; 9 $scope.NumberTwo = 0; 10 $scope.Result = 0; 11 $scope.Decimals = 2; 12 $scope.Multiply = function () { 13 $scope.Result = $scope.NumberOne * $scope.NumberTwo; 14 }; 15 }

Line (3) of the controller now takes two parameters, first argument will always be the input and second one is number of digits. For sake of simplicity I am not checking isNaN etc., in the ‘twoDigits’ method. Here is the jsFiddle of the solution.

Suppose you may want to pass more than one argument to the filter function, then you will simple concatenate the arguments as

{{ input | filter: arg1 : arg2 : arg2}} 

I found filter to be very powerful and useful.

Silverlight to Angular – 4 (DataTemplates)

In Silverlight, when you are rendering some complicated data in a control, you will use DataTemplate to make it more readable to the user. One simple example would be, if you have a ListBox and you normally put a single property like state or year etc.,. But you will run into a situation, where you may want to display more than one property per row. One such example is displaying Diggs story to demonstrate the use of Listbox in Silverlight. For sake of simplicity, we will look a very simple example.

Problem: Display all students with their ID and Name in a listbox to select.

Silverlight:

By default, when you use ListBox in silverlight, you can bind it to a collection and point to a property of the object in the collection to display. If you want to display more than one properties from the object, then you need to use ItemTemplate. That is what we are going to do. For this example, we have a collection of Students, with following properties

1 public class Student 2 { 3 public string Id { get; set; } 4 public string Name { get; set; } 5 public string Grade { get; set; } 6 }

Since we need to work with collection to bind to control’s itemsource, we will create an observable collection of students like the following

1 public class Students:ObservableCollection<Student> 2 { 3 public Students() 4 { 5 Add(new Student() {Id = "1", Name = "First", Grade = "A"}); 6 Add(new Student() {Id = "2", Name = "Second", Grade = "B" }); 7 Add(new Student() { Id = "3", Name = "Third", Grade = "C" }); 8 9 } 10 }

View:

In our View, we will create a Listbox control and bind the Students collection to it. We are planning to display for now, just the Id and Name. Since the control’s DisplayMembersPath limitation, we will create a ItemTemplate to host the data template.

1 <ListBox ItemsSource="{Binding CurrentStudents}" Grid.Column="1" Margin="36,5,36,10"> 2 <ListBox.ItemTemplate> 3 <DataTemplate> 4 <Grid> 5 <Grid.ColumnDefinitions> 6 <ColumnDefinition Width="20*"></ColumnDefinition> 7 <ColumnDefinition Width="*"></ColumnDefinition> 8 </Grid.ColumnDefinitions> 9 <TextBlock Text="{Binding Id}" Grid.Column="0"></TextBlock> 10 <TextBlock Text="{Binding Name}" Grid.Column="1"></TextBlock> 11 </Grid> 12 </DataTemplate> 13 </ListBox.ItemTemplate> 14 </ListBox>

Nothing special here, We assigned the ObservableCollection of Students to the ListBox, and then we create a gird inside each row of ListBox and display Id and Name.

ViewModel:

This exposes a property for CurrentStudents, nothing else

1 public ObservableCollection<Student> CurrentStudents 2 { 3 get 4 { 5 return new Students(); 6 } 7 }

Most of the work we need to do is in the View to tell the Silverlight to create each row of ListBox with more than one property of the object collection.

AngularJS:

To my surprise, the amount of code we need to write to achieve the same is very less in Angular, there is not a lot of ceremony in here. The only and the main difference here between Silverlight and Angular is the building elements for the collection. In Silverlight we just pass the collection information and property to use in XAML and Silverlight takes care of traversing through the collection and building each row and putting the values property. Angular behaves same way except except instead of just pointing to the collection as itemssource, in angular, you will write the ‘foreach item in collection’ in the element instead of just the collection. Other than that everything from programming side is same. With that lets look at the view. The main difference is in the view, so lets make sure we understand it.

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="TemplateCtrl"> 8 <select ng-model="SelectedItem"> 9 <option ng-repeat="student in Students"> 10 {{student.Id}}-{{student.Name}} 11 </option> 12 </select> 13 </div> 14 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 15 <script src="Scripts/TemplateCtrl.js"></script> 16 </body> 17 </html>

If you are following my previous blogs, you should be ok till line (8). Line (8) specifies that you are creating a list box (HTML – Select) and ignore the rest in line(8) for now. Line (9) – (11) specifies, what are the things goes into each and every options.

<option ng-repeat="student in Students">

In line (9) there is a new directive that we haven’t used before. ng-repeat, tells angular to create individual element for each and every object in a collection. In this example, angular will create individual option element for every object in ‘Students’ collection based on the template specified in line (10). So if we are going by the collection we created in the Silverlight view model, there are 3 students which means, Angular will create 3 option elements. Line (10) is a simple template, which does nothing but a simple one way binding of Id and Name properties of student class.

ViewModel:

As you can expect, most of the work is in the View since template work is UI related and ViewModel does not have any idea about templates. So our view model looks like the following

1 function TemplateCtrl($scope) { 2 $scope.Students = [ 3 { Id: "1", Name: "First", Grade: "A" }, 4 { Id: "2", Name: "Second", Grade: "B" }, 5 {Id: "3", Name: "Third", Grade: "C"}]; 6 }

I skipped ‘SlectedItem’ on purpose for now.

Silverlight to Angular – 3 (Commands)

In Silverlight, we use Commands to do clean separation of View and ViewModel. If we were not using commanding, we will end up creating code behind code to handle the events fired by the controls and then publish the message from view to viewmodel or call viewmodel method from view. Either way, there is unnecessary code in code behind. With command, we can bind the command to a control event using magic black box (in my case Jounce or your ICommand implementation) which will take care of the wiring control event directly to viewmodel method, leaving our code very clean.

We will reuse the code we did in the last blog since it already has commanding implementation. If you want to know more about how to do commanding, please take a look at the Jounce Command documentation or one of my old blog on commanding.

Problem: Display number of times a button is clicked.

I am not going to explain the Silverlight solution here since it is already explained here. Let’s look at the AngularJS solution here since I conveniently skipped it in the previous blog.

View:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="Controller"> 8 Number of Clicks:{{NumberOfClicks}} 9 <button ng-click="onClick()">Click Me</button> 10 </div> 11 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 12 <script src="Scripts/Controller.js"></script> 13 </body> 14 </html>

In this example we are interested in line (9). Angular provides a cool directive ‘ng-click’ which will listen to the click event and calls a function in the controller or if it is an expression then it evaluate the expression. It is as simple as that. So in Angular, if you want to use commanding to do clean separation of view and controller, all you have to do is use ng-click directive on a button. From view model perspective, the function view is calling nothing more than just another function and nothing special about it. There are bunch of APIs you can use to create this commanding behavior on different controls and you can find them all here in Angular API directive.

Controller:

1 function Controller($scope) { 2 $scope.NumberOfClicks = 5; 3 $scope.onClick = function() { 4 $scope.NumberOfClicks = $scope.NumberOfClicks + 1; 5 }; 6 }

In Silverlight, not only we can execute the action through command, we have another option enable the command or not. This can be achieved using ng-disabled directive. Will look at how to use that in the following example. One benefit in Angular is that you can pass as many parameters as you want in the function call instead of just one in Silverlight. Let’s take a look at a sample where we can pass multiple parameters in function call.

Following example allow user to enter two numbers and perform an addition and display result. When the user enters non numeric number we want to disable the ‘Sum’ button.

View:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body ng-controller="Controller"> 7 First : <input ng-model="numberOne"/><br/> 8 Second: <input ng-model="numberTwo"/><button ng-disabled="IsValid(numberOne, numberTwo)" 9 ng-click="onClick(numberOne, numberTwo)">Sum</button><br/> 10 Sum: {{sum}} 11 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 12 <script src="Scripts/Controller.js"></script> 13 </body> 14 </html>

Both first and second number are two-way binding since the user change need to be propagated to model. On button click, we are using ng-click directive to call ‘onClick’ function in the controller and we are passing two parameters numberOne and numberTwo from the UI. If you notice, we also have another directive called ng-disabled, this will make the element disable if it return associated function from control returns false. If the input data collection is a form then you can enable and disable form submit button using Form.$validate.

Controller:

This is nothing but simple java script code which has variable assignments and a function call.

1 function Controller($scope) { 2 $scope.numberOne = 0; 3 $scope.numberTwo = 0; 4 $scope.sum = 0; 5 $scope.onClick = function(first, second) { 6 $scope.sum = Number(first) +Number(second); 7 }; 8 $scope.IsValid = function(first, second) { 9 return !(isNumber(first) && isNumber(second)); 10 }; 11 function isNumber(n) { 12 return !isNaN(parseFloat(n)) && isFinite(n); 13 } 14 }

One another point of interest along the line of ng-click is about other events from other elements. Take a look at this stack overflow question and answer. At the end, there is a comment by Tim Steward which is very interesting. He pointed out that if you do not see any ng- function for the element you are working on, his suggestion is to use Angular-UI

Silverlight to Angular – 2 (Data Binding)

One of the main features in Silverlight is binding. There are two ways you do data binding. ‘One way’ or ‘two way’ data binding. There is one more ‘onetime’, I am skipping it on purpose here. Let’s first see what they are and when do you use them and then see its associated implementation in both Silverlight and Angular.JS

One-way: As the name suggests, as the data in data model changes, the changes are reflected in the View. When it is a one way data binding, user is not allowed to change the value in the view. It is meant to be showing the data coming from the model only. The read only controls are the excellent candidates for this kind of binding. This eliminates the overhead of two way binding.

image

Problem: Display number of times a button is clicked using one-way binding.

Silverlight:

View: For our problem, we need three controls.

  1. A text block with text specifying the ‘Number of clicks:’
  2. A text block which displays number of clicks itself.
  3. A button to click to modify the data.
1 <TextBlock Grid.Row="0" Grid.Column="0">Number of Clicks: </TextBlock> 2 <TextBlock Grid.Row="0" Text="{Binding NumberOfClicks, Mode=OneWay}" Grid.Column="1"/> 3 <Button Grid.Column="1" Grid.Row="1" Command="{Binding ClickMe}" CommandParameter="">Click me</Button>

ViewModel: We have a public property called ‘NumberOfClicks’ which is what bound to our text block to show number of times the button clicked. The second one is IActionCommand to trigger click event for the button. Every time button clicked, we increment the counter and raise the property changed event so that view can pick up the modified value.

1 [ExportAsViewModel(typeof(MainPageViewModel))] 2 public class MainPageViewModel:BaseViewModel 3 { 4 public IActionCommand<string> ClickMe { get; private set; } 5 private int _numberOfClicks = 0; 6 public int NumberOfClicks 7 { 8 get { return _numberOfClicks; } 9 set { _numberOfClicks = value; RaisePropertyChanged(()=>NumberOfClicks); } 10 } 11 12 public MainPageViewModel() 13 { 14 ClickMe = new ActionCommand<string>(p=> NumberOfClicks = NumberOfClicks+1); 15 } 16 }

Angular:

In Angular, to achieve one way binding, i.e., $scope -> view, all you do is to use ng-bind directive instead of ng-model. Alternate solution is to use the default {{variable}} notation, which also behaves same way as the ng-bind. I prefer {{variable}} approach. Here is an example which demonstrate one way binding using ng-bind.

View:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="Controller"> 8 Number of Clicks:{{NumberOfClicks}} 9 <button ng-click="onClick()">Click Me</button> 10 </div> 11 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 12 <script src="Scripts/Controller.js"></script> 13 </body> 14 </html>

Line (8) is the one way binding. Even though ng-bind was not specified, it is the default binding. So you do not explicitly specify the ng-bind and I prefer to stay with {{}} approach.

ViewModel/Controller:

1 function Controller($scope) { 2 $scope.NumberOfClicks = 5; 3 $scope.onClick = function() { 4 $scope.NumberOfClicks = $scope.NumberOfClicks + 1; 5 }; 6 }

[Note: When you run the code, if the number is not incrementing then, one possibility is that, you might not have ‘()’ next to the onClick function in the HTML. Been there done that.]

Two-way: This is the standard and most used data binding. In this type of binding, when a data in data model changes, the changes reflected in View. In the same way, user is allowed to change the data in view and the change pushed to Model. In my opinion this is what made Silverlight so awesome and now it carries to Angular.

image

Problem: Get name from user and provide a greeting to the user. Allow user to add ‘!’ to the end of the name using a button.

Silverlight: For our problem we need three controls

View:

  1. A text block which display ‘Enter Name’.
  2. A text box to get user name.
  3. A text block to display ‘Hello {name}’.
  4. A button to add ‘!’ char to the name, which should modify both the (2) and (3) control values.
1 <TextBlock>Name: </TextBlock> 2 <TextBox Grid.Column="1" Text="{Binding Name, Mode=TwoWay}"></TextBox> 3 <Button Command="{Binding ClickMe}" CommandParameter="" Grid.Column="2">Add !</Button> 4 <TextBlock Grid.Row="1" Text="{Binding HelloName}"></TextBlock>

If you notice line (2) the text box binding ‘Name’ is set to ‘TwoWay’, which means, user is allowed to enter data which will change the viewmodel, but if the data changes in the model, it get reflected back on the view as well.  When you run the code, you will notice, when user enters ‘Unni’ in the name and press the button, it not only display ‘Hello Unni!’ in the text block in line (4) but also changes the text box (line 2) to ‘Unni!’. In this example, line (4) is still one way, so when data changes in the model, the change will get reflected in the view.’

ViewModel:

1 [ExportAsViewModel(typeof(MainPageViewModel))] 2 public class MainPageViewModel:BaseViewModel 3 { 4 private string _name; 5 public string Name 6 { 7 get { return _name; } 8 set 9 { 10 _name = value; 11 RaisePropertyChanged(() => Name); 12 } 13 } 14 public IActionCommand<string> ClickMe { get; private set; } 15 16 private string _helloName; 17 18 public string HelloName 19 { 20 get { return _helloName; } 21 set 22 { 23 _helloName = value; 24 RaisePropertyChanged(() => HelloName); 25 } 26 } 27 28 public MainPageViewModel() 29 { 30 ClickMe = new ActionCommand<string>(Clicked); 31 } 32 33 public void Clicked(string obj) 34 { 35 if (!Name.EndsWith("!")) 36 Name += "!"; 37 HelloName = "Hello " + Name; 38 } 39 }

[Note: If you have trouble with the code, make sure, all the properties have RaisePropertyChanged event in it. Also make sure the button click command name matches the command in the view model. The last part make sure all the exports attributes are marked properly]

Angular:

By default, if you do not specify ng- in the element, then one way binding is assumed. It means, whenever you use {{variable}}, it is considered one way binding. Anytime data change happens in the controller, view gets the modified data. $scope -> view. On the other hand if you specify ‘ng-model’ attribute in the element, it is considered two way binding. It means, user changes will be pushed to model and any model changes will be pushed to view. $scope <-> model.

View:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="controller"> 8 Name: <input ng-model="Name"/> 9 <button ng-click="onClick()">Click Me</button> 10 <br />{{HelloName}} 11 </div> 12 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 13 <script src="scripts/controller.js"></script> 14 </body> 15 </html>

Line (8) is a two way binding to a variable ‘Name’ in the $Scope. It means, when user enters a value in the input, the user entered value get pushed to the $scope variable Name. On the other hand, line (10), when ever there is a value change to ‘HelloName’ variable in $scope, it get pushed to the view.

ViewModel/Controller: (Going forward, I am going to refer this as Controller instead of ViewModel).

1 function controller($scope) { 2 $scope.Name = ""; 3 $scope.HelloName = ""; 4 5 $scope.onClick = function () { 6 debugger; 7 if ($scope.Name[$scope.Name.length - 1] !== "!") 8 $scope.Name = $scope.Name + "!"; 9 $scope.HelloName = 'Hello ' + $scope.Name; 10 }; 11 }

Initially when the HTML is rendered in the browser, both Name and HelloName will have empty string. When the user enters a value, say ‘Unni’ in the input box and click on ‘Click Me’ button, controller executes ‘onClick’ function and sets the Name to ‘Unni!’ (note ‘!’ at the end) and make ‘HelloName’ as ‘Hello Unni!’. So both the variables ‘Name’ and ‘HelloName’ changed in the model so the changes pushed back to view. Now if you notice, your input changed to Unni! Instead of Unni, thus making variable ‘Name’ two way binding. While HelloName pushed to view with new value making it one way binding.

So the bottom line is, if you use ‘ng-model’, it is two way binding otherwise it is one way binding.

Silverlight to Angular – 1

So from my previous blog you all know that I am moving towards Angular for our front end development. I am planning to write series of blogs on how to take Silverlight knowledge to Angular. But if you want to learn Angular without the Silverlight background, please head to this great example. Without further ado, lets look at our hello world program.

Problem: We are asked to create an app, which will display ‘Hello World’.

Silverlight:

As you all know, Silverlight follows MVVM pattern. In this case, all we need to do is to display a static text ‘Hello World’. So there is no need for Model or ViewModel here. All we need is simple XAML with a TextBlock which displays ‘Hello World’ like the following

<Grid x:Name="LayoutRoot" Background="White">
    <TextBlock HorizontalAlignment="Left"  TextWrapping="Wrap" Text="Hello World" VerticalAlignment="Top"
               Height="25" Width="289"/>
</Grid>

So in here XAML is the ‘V’ ( – View) in the ‘MVVM’. Nothing complicated here, very simple. Compile and run the app and you will get a very simple ‘Hello World’.

Angular:

Now switching the focus to Angular world. Before we dig deep into Angular, we need to understand what is Front End Framework (FeF). If you are to develop application using HTML, you would use HTML for rendering page, CSS for styling and Javascript to handling client side processing. To create a dynamic, responsive web page, we will need to lot of work with Javascript and ton of DOM manipulation. So here is where FeF to help. There are ton of FeF is available today. They all abstract the common tasks that we would do and make our development easy to create responsive and cross browser support (with limitation) application. With FeF, we can focus on building our application rather than worry about browsers and ugly DOM manipulation.  Angular is one such framework backed by Google. I do not want to go into details of what it gives out of the box since it is very well documented in angular website.

Before we go into Angular development, have a look at a mapping between Angular and Silverlight.

clip_image001[6]
clip_image002[6]

Angular framework also support and promotes MV* model development. Igor from Angular wrote a short take on whether Angular is a MVC or MVVM and his conclusion is Angular is MVW pattern where ‘W’ stands for whatever you want it to be, Controller or View Model. Sticking with Silverlight model, I will try to related to VM as we go along. Coming back to the problem at hand, what we need to display is a static ‘Hello World’ text and in our Silverlight application, we put the text directly in the view and that is what we are going to do here as well. Going by above picture all we need to do is to put ‘Hello World’ and we are done. So here is the simple HTML which displays ‘Hello World’.

head>
    <title></title>
</head>
    <body>
        <p>Hello World</p>
    </body>
</html>

So your question is, where is Angular? You do not need Angular since all our work is in the View. In FeF, the view is nothing more than HTML (for now).

If I stop the blog right here, then I am really cheating, we did not see any Angular here. So we are going to modify the problem little bit different. So here is the new problem statement.

Problem: We are asked to create program to display a value of string variable ‘DisplayData’, where ‘DisplayData’ contains ‘Hello World’.

Silverlight:

(You can get the full solution of Silverlight and Angular from https://www.dropbox.com/sh/nh7ihjrqlhiax02/RrkmDC-6qL)

As you know from my previous blogs, I am a big fan of Jounce framework for my Silverlight development. If you are not familiar with Jounce framework, don’t worry, the concepts we are going to look at should be easy to follow. If you are a hard core Silverlight developer and not using any MVVM framework, I would strongly recommend you to take a look at this framework. Anyway, Lets look at the code we would write to display ‘Hello World’ from view model.

View: (MainPage.XAML)

<Grid x:Name="LayoutRoot" Background="White">
        <TextBlock HorizontalAlignment="Left"  TextWrapping="Wrap" Text="{Binding DisplayData}" VerticalAlignment="Top"
                   Height="25" Width="289"/>
    </Grid>

 

ViewModel:

public class MainPageViewModel:BaseViewModel
    {
        public string DisplayData
        {
            get { return "Hello World"; }
        }
    }

Jounce has couple of ways to do the view and viewmodel association. I am using traditional explicit Export attribute to mark view and viewmodel and let Jounce do the mapping. As a Silverlight developers we know how this thing work and how data binding happen so I will stop here.

Angular:

One of the main reason I am really attracted to Angular is the out of the box data binding. By the way Knockout framework also support data binding like Silverlight. Lets start our actual Angular code. Even though it is simple Hello World, I would like to follow same MVC pattern. First and fore most, I am doing all the development in Visual Studio 2012. I will do a quick walk through on what do I do for HTML5 development.

  1. For our testing either you can download angular.js locally and use that for our coding or point directly to the minified version in the web.
  2. Create a directory where you want to create the new html page.
  3. Open Visual Studio and create new ‘Blank Project’. (If you do not see it, search for blank template on search it will show up).
  4. Select Solution and Add existing web page and use file system and point to the empty directory you have created.
  5. Create a new folder called ‘Scripts’ where we will keep all the java scripts.

View: (Home.html)

<!DOCTYPE html>
<html ng-app>
<head>
</head>
    <body>
        <div ng-controller="Controller">{{DisplayData}}</div>
        <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
        <script src="Scripts/Controller.js"></script>

    </body>
</html>

 

Controller: (scripts\Controller.js)

function Controller($scope) {
    $scope.DisplayData = "Hello World";
}

So there are two code, one is HTML and another one is pure java script. Lets look at the HTML first and see if we can make any sense of it.  To make it simple, let us focus only on the bolded words, rest of it normal HTML.

  1. ng-app: Every angular application should have one and only ng-app. When HTML is been rendered on the browser, once Angular gets the execution context, it will try to find the application scope. In our case, we have ng-app set at <HTML> tag that means, angular will look for angular directives in all DOM elements. We can even have the ng-app set to a simple and single <DIV>, then the scope is limited to the <DIV>. The bottom line, you need to have one ng-app.
  2. ng-controller: This is one of the important directive you need to know. This is the one which connects, view to the controller like the ‘[Export]’ we did in Silverlight. You can have multiple controller in a single view (HTML) but only one ng-app. In our example, we have one controller called ‘Controller’ assigned to a <DIV> DOM object. So everything under DIV will get evaluated with this associated controller.
  3. {{variable}}: The double curly braces are nothing but data binding or ‘{Binding variable}’ in Silverlight. Same as in Silverlight, when you use a Binding variable, Silverlight will look for it in the associated ViewModel, in this case, Angular will replace the variable with value from associated controller.

If you are interested in how these ng- directives are processed and how you got the hello world, instead of me repeating it as third person, take a look at this awesome information in Angular web site.

Next stop is controller script. This script is very simple. We have a controller object and it gets its scope as a parameter. If you remember, in the view, you can set the ng-controller to any DOM element. The $scope is suppose to cover all the DOM elements with in it. So in our example, the controller is associated with all the elements under the <DIV> element. So when angular process the DOM elements, it will look for DisplayData under Controller object and it find the ‘Hello World’ and populates the  value.

If you have any questions or doubt, please send me a note and I will try to answer. When you are working through the examples, if you run into any problems, I would recommend check out Forum at Stack Overflow.

Silverlight to Angular JS

With heavy and broken heart finally it is time for me to say good bye to one of the best technology that I worked with,  ‘Silverlight’. There is always people argue about the validity and are so happy about the Silverlight demise. In my opinion as a developer, I really enjoyed developing apps in Silverlight. The best part of course was data binding. So simple concept that made the coding very easy and also the separation of view and view model so clean. XAML was so easy to create view without getting too much business and so on. Now we are not talking about Silverlight but the next big thing. It is without doubt HTML5, Microsoft was very quick and wise to adopt it. As the technology progress, it is time for me to make the switch as well. So lately I started poking at various options available today to make the transition into HTML5.

As a silverlight developer, I follow John Papa and he is been promoting Knockout JS. I saw couple of videos and did some coding with it and it looks good. From Silverlight,  it is a natural transition. While Knockout is pretty good, there is another cool kid in the block and is Angular JS. Similar to Knockout, Angular also have great tutorials, decent following in forums. One of the things I was looking for when I started learning Angular of course is data binding and it is rich. I fell in love with it on my second data binding exercise. So I am going to head into HTML5 with Angular for client side development. I have not decided on the server side technologies yet. If any one have any good comments or suggestions please feel free to send me a note or command.

Some good references for Angular:

Home – http://angularjs.org/

Screencasts – http://www.egghead.io/

Blogs – http://blog.angularjs.org/

As I move from Silverlight to Angular I found a better IDE to go with it. Webstrom is so far the best IDE I found for angular development.

So my friend ‘Silverlight’ Good Bye.

Use PromptBox to get simple user input in Silverlight

When we create Silverlight application we will run into a situation where we need to get very simple input from a user apart from traditional ok or cancel. If you are after the simple ok or cancel then message box serve the purpose but if you need to get some kind of data from the user as simple as a number or a string, then we do not need to create popup window or child window in Silverlight if you are using component one controls.

Out of the box, component provides a user control called C1PromptBox which as the name suggests, prompt the user for an input and goes on it merry way without cluttering code with complicated code.

Let’s look at this with simple example;

C1PromptBox.Show(“Enter your age”, “Age prompt”, (s, r) =>
{
If (r ==MessageBoxResult.OK)
{
//age will be in s, parse the age out
}
else
{
// user pressed cancel
}
}

If you expect the last two line to execute after getting user input, then if condition has to be inside the C1PromoptBox.Show bot outside like the code shown

above. The proper way to write the code

In the above example, when the code executes it will prompt the small message box to enter the age and you parse or handle the value on the event user press ok button.

One thing we need to be mindful, the Show event is a delegate so if you have any instructions that need to execute after prompt is successful, it has to be inside the MessageBoxResult.OK condition not outside the show delegate since UI will take control back after show event is successful.

Here is a scenario;

  1. public void PromptAge()
  2. {
  3. int age = 0;
  4. C1PromptBox.Show(… get age);
  5. if (age <= 30)
  6. HandleLessThanThirtyAge();
  7. }
 

In the above example we are expecting the dialog to be shown for user to enter the age. After the user enters the age, line 05 gets control and executes HandlesLessThanThirtyAge method if the age is less than or equal to 30. But that is not how it works. When PromptAge executes, it execute prompt box and while it wait for user to enter something, the UI thread continues and executes 05 through so age will be always 0 and it never executes the method on 06. The reason for that is, the behavior on how to handle ok or cancel is delegate inside the prompt box. So for it work properly. ie, after user enters the ages, get the age and based on the age to execute the HandleLessThanThirtyAge, we need to move the if condition inside the PromptBox delegate itself as shown below

  1. public void PromptAge()
  2. {
  3. C1PromptBox.Show("msg", "prompt", (s, r) =>
  4. {
  5. if (r == MessageBoxResult.OK)
  6. {
  7. //parse age from s
  8. if (age <= 30)
  9. HandleLessThanThirtyAge()
  10. }
  11. };
  12. }
One of the feature missing in this is default value for the prompt, I requested this feature with Component One and it is schedule be part of their feature release. By providing most commonly used value as default value, we could save one key stoke for the user. Once the feature is available I will update this blog.