angular-formly
JavaScript powered forms
![](https://s3.amazonaws.com/media-p.slid.es/uploads/55780/images/1638291/angular-formly-logo-256px.png)
images provided for your amusement by characterslist.com
by Kent C. Dodds
@kentcdodds
@kentcdodds
Kent! Don't forget to Selfie!
Time to wake up
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1071657/squat.png)
@kentcdodds
Air Squats
Kent C. Dodds
@kentcdodds
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1071649/alianza.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1071652/15510_14.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1071655/Screen_Shot_2015-02-13_at_9.28.38_AM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/55780/images/1638288/angular-air-256.png)
@kentcdodds
What
Is
Formly?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064653/star-wars_16.jpg)
@kentcdodds
Change this
To this
<form name="vm.userForm" ng-submit="vm.onSubmit(vm.user)">
<div class="form-group" has-error="vm.userForm.firstName">
<label for="firstName">First Name</label>
<input type="text" ng-model="vm.user.firstName" name="firstName" class="form-control" id="firstName" placeholder="First Name" required>
<div my-messages="vm.userForm.firstName"></div>
</div>
<div class="form-group" has-error="vm.userForm.lastName">
<label for="lastName">Last Name</label>
<input type="text" ng-model="vm.user.lastName" name="lastName" class="form-control" id="lastName" placeholder="Last Name" required>
<div my-messages="vm.userForm.lastName"></div>
</div>
<div class="form-group" has-error="vm.userForm.email">
<label for="emailAddress">Email Address</label>
<input type="email" ng-model="vm.user.email" name="email" class="form-control" id="emailAddress" placeholder="Email address" required>
<div my-messages="vm.userForm.email"></div>
</div>
<div class="form-group" has-error="vm.userForm.confirmEmail">
<label for="emailAddressConfirm">Confirm Email Address</label>
<input type="email" ng-model="vm.user.confirmEmail" name="confirmEmail" must-match="vm.user.email" class="form-control" id="emailAddressConfirm" placeholder="Confirm Email address" required>
<div my-messages="vm.userForm.confirmEmail"></div>
</div>
<div class="form-group" has-error="vm.userForm.password">
<label for="password">Password</label>
<input type="password" ng-model="vm.user.password" name="password" class="form-control" id="password" placeholder="Password" required>
<div my-messages="vm.userForm.password"></div>
</div>
<div class="form-group" has-error="vm.userForm.confirmPassword">
<label for="passwordConfirm">Confirm Password</label>
<input type="password" ng-model="vm.user.confirmPassword" must-match="vm.user.password" class="form-control" id="passwordConfirm" placeholder="Password" required>
<div my-messages="vm.userForm.confirmPassword"></div>
</div>
<div class="radio-group" has-error="vm.userForm.genderRadios">
<label>Your Gender?</label>
<div class="radio">
<label>
<input type="radio" ng-model="vm.user.model" name="genderRadios" id="genderRadios1" value="male" required>
Male
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="vm.user.model" name="genderRadios" id="genderRadios2" value="female" required>
Female
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="vm.user.model" name="genderRadios" id="genderRadios3" value="unspecified" required>
Prefer not to say
</label>
</div>
<div my-messages="vm.userForm.genderRadios"></div>
</div>
<div class="checkbox" has-error="vm.userForm.agree">
<label>
<input type="checkbox" name="agree" ng-model="vm.user.agree" required> Do you sign your soul away to our TOS?
</label>
<div my-messages="vm.userForm.agree"></div>
</div>
<button type="submit" class="btn btn-default" ng-disabled="vm.userForm.$invalid">Submit</button>
</form>
<form name="vm.userForm" ng-submit="vm.onSubmit(vm.user)">
<formly-form model="vm.user" fields="vm.fields" form="vm.userForm">
<button type="submit" class="btn btn-default" ng-disabled="vm.userForm.$invalid">
Submit
</button>
</formly-form>
</form>
... and a little JS :-)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064702/star-wars_15.jpg)
@kentcdodds
It brings:
- Maintainability
- Consistency
- Flexibility
- Simplicity
- Sanity
- etc....ity :-)
To forms in AngularJS Apps
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064850/star-wars_5.jpg)
@kentcdodds
But I
❤️
HTML!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064756/star-wars_11.jpg)
@kentcdodds
No
You
Don't...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064757/star-wars_4.jpg)
@kentcdodds
<input ng-model="vm.user.firstName" />
@kentcdodds
<div>
<label>First Name</label>
<input ng-model="vm.user.firstName" />
</div>
@kentcdodds
<div>
<label for="name">First Name</label>
<input ng-model="vm.user.firstName" id="name" />
</div>
@kentcdodds
<div class="form-group">
<label for="name">First Name</label>
<input ng-model="vm.user.firstName"
id="name"
class="form-control"
/>
</div>
@kentcdodds
<div class="form-group">
<label for="{{::vm.id}}">{{vm.label}}</label>
<input ng-model="vm.model"
id="{{::vm.id}}"
class="form-control"
/>
</div>
angular.module('app').directive('nlInput', function() {
var unique = 0;
return {
restrict: 'E',
template: require('./nl-input.html'), // webpack ftw
replace: true,
scope: {
label: '@',
model: '='
},
bindToController: true,
controllerAs: 'vm',
controller: function() {
var vm = this;
vm.id = `field${Math.floor(Math.random() * 999)}${unique++}`; // es6 ftw
}
};
});
@kentcdodds
<div class="form-group">
<label for="{{::vm.id}}">{{vm.label}}</label>
<input ng-model="vm.model"
id="{{::vm.id}}"
class="form-control"
ng-required="vm.required"
/>
</div>
angular.module('app').directive('nlInput', function() {
var unique = 0;
return {
restrict: 'E',
template: require('./nl-input.html'), // webpack ftw
replace: true,
scope: {
label: '@',
model: '='
},
bindToController: true,
controllerAs: 'vm',
controller: function() {
var vm = this;
vm.id = `field${Math.floor(Math.random() * 999)}${unique++}`; // es6 ftw
},
link: function(scope, el, attrs) {
scope.vm.required = attrs.hasOwnProperty('required');
}
};
});
<div class="form-group">
<label for="{{::vm.id}}">{{vm.label}}</label>
<!-- but let's be honest... this is getting ridiculous (-‸ლ) -->
<input ng-model="vm.model"
id="{{::vm.id}}"
class="form-control"
ng-required="vm.required"
ng-disabled="vm.disabled"
ng-maxlength="vm.maxlength"
ng-minlength="vm.minlength"
/>
</div>
angular.module('app').directive('nlInput', function() {
var unique = 0;
return {
restrict: 'E',
template: require('./nl-input.html'), // webpack ftw
replace: true,
scope: {
label: '@',
model: '='
},
bindToController: true,
controllerAs: 'vm',
controller: function() {
var vm = this;
vm.id = `field${Math.floor(Math.random() * 999)}${unique++}`; // es6 ftw
},
link: function(scope, el, attrs) {
// I'm not a fool, let's JavaScript here
var extraAttrs = ['required', 'disabled', 'maxlength', 'minlength'];
angular.forEach(extraAttrs, attr => {
scope.vm[attr] = attrs.hasOwnProperty(attr);
});
}
};
});
Oh, yeah, validation please?
Sure, yeah... cool... uh...
Give me a sec to write a directive and update everything...
done!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064915/star-wars_12.jpg)
@kentcdodds
So uh... yeah, we're changing... everything
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067299/star-wars_2.jpg)
@kentcdodds
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067302/impossible.png)
@kentcdodds
It doesn't
have to be
this way...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064800/star-wars_8.jpg)
@kentcdodds
angular-formly
JavaScript powered forms for AngularJS
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064808/star-wars_14.jpg)
[coding forms without angular-formly] leads to anger
anger leads to hate
hate... leads to suffering
- Yoda (presenter liberties taken)
@kentcdodds
Live-code time
(ó ì_í)=óò=(ì_í ò)
@kentcdodds
Expression Properties
Total Control
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067217/star-wars_7.jpg)
@kentcdodds
Auto-magical attributes
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067207/star-wars_10.jpg)
@kentcdodds
Validation
consistent & simple
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067213/star-wars_3.jpg)
@kentcdodds
Wrappers
DRY HTML
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1064649/star-wars_13.jpg)
@kentcdodds
Custom Templates
Dead simpler than dead simple
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067229/star-wars_19.jpg)
@kentcdodds
But Wait! There's More!
but there's not enough time...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/kentcdodds/images/1067496/star-wars_21.jpg)
bit.ly/ngFormly
@kentcdodds
Thanks!
Give it a go!
@kentcdodds
Slides: bit.ly/ng-formly-slides
Feedback please: bit.ly/ng-formly-feedback
angular-formly
By Kent C. Dodds
angular-formly
Learn why you don't like html and angular-formly can help you with that :-)
- 9,750