Init Ng-Model from Form Fields Attributes

I have been using AngularJS's magic in some non single page applications to improve user experience and provide an instant feedback.

A few days ago, not for the first time, I faced the issue to need starting form fields with server side provided data while making use of awesome AngularJS feautures.


Suppose we have an HTML like that:

<!DOCTYPE html> <html lang="en" ng-app=""> <head> <script src="//"></script> </head> <body> <input type="text" value="John" ng-model="name"> </body> </html>
See the Pen gBoEa by Glauco Custódio (@glaucocustodio) on CodePen.

You can see that the value "John" is not being filled in input. By default, AngularJS does not initialize ng-model based on form fields attributes like value, checked and selected. Looking for some way to pull it off, I found three manners and I wanna share them with you.

Initialize Variable in Controller

The "angular" way I read around is to set the value inside a controller:

var app = angular.module('myApp', []); app.controller('MyCtrl', function ($scope) { $ = 'John'; });
See the Pen Beldq by Glauco Custódio (@glaucocustodio) on CodePen.

But when our entire page is coming from server, it does not seem a good approach, we would need mix the server language with JavaScript or mess up with another not cool thing.

Use Ng-Init Directive

The second one is about setting variable value inside ng-init:

<!DOCTYPE html> <html lang="en" ng-app=""> <head> <script src="//"></script> </head> <body> <input type="text" ng-model="name" ng-init="name='John'"> </body> </html>
See the Pen pIkdw by Glauco Custódio (@glaucocustodio) on CodePen.

It works. But I personally guess we can improve it.

Use a Custom Directive

Finally, we can use a custom directive to load values based on form fields attributes:

angular.module('initFromForm', []) .directive('ngInitial', function() { return { restrict: 'A', controller: [ '$scope', '$element', '$attrs', '$parse', function($scope, $element, $attrs, $parse) { var getter, setter, val; val = $attrs.ngInitial || ($element.attr("checked") !== undefined ? true : '') || $attrs.value || $element.val() getter = $parse($attrs.ngModel); setter = getter.assign; setter($scope, val); } ] }; }); var app = angular.module('myApp', ['initFromForm']);
See the Pen nhcmz by Glauco Custódio (@glaucocustodio) on CodePen.

This directive is a improved version I made from this one to support textarea, checkbox and radio as well.

I really appreciated this approach, we just need add initial-value attribute to form field and voilà.

Do you know another way to do the same? Share with us in the comments.

See you.

Written on October 20, 2014