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.
Hands-on
Suppose we have an HTML like that:
<!DOCTYPE html> <html lang="en" ng-app=""> <head> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js"></script> </head> <body> <input type="text" value="John" ng-model="name"> </body> </html>
See the Pen gBoEa by Glauco Custodio (@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) { $scope.name = 'John'; });
See the Pen Beldq by Glauco Custodio (@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="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js"></script> </head> <body> <input type="text" ng-model="name" ng-init="name='John'"> </body> </html>
See the Pen pIkdw by Glauco Custodio (@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 Custodio (@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.