<html>
<head>
<!-- Twitter bootstrap -->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<!-- apiCheck is used by formly to validate its api -->
<script src="//rawgit.com/kentcdodds/apiCheck.js/master/dist/api-check.js"></script>
<!-- This is the latest version of angular (at the time this template was created) -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
<!-- This is the current state of master for formly core. -->
<script src="https://rawgit.com/formly-js/angular-formly/master/dist/formly.js"></script>
<!-- This is the current state of master for the bootstrap templates -->
<script src="//rawgit.com/formly-js/angular-formly-templates-bootstrap/master/dist/angular-formly-templates-bootstrap.js"></script>
<title>Angular Formly Example</title>
</head>
<body ng-app="formlyExample" ng-controller="MainCtrl as vm">
<div>
<h1>angular-formly example: {{vm.exampleTitle}}</h1>
<div>
This demonstrates using <code>formly-form</code> inside of a template in order to accomplish
repeating fields. It also uses <code>formly-field</code> inside of a template in order to
accomplish an advanced layout.
</div>
<hr />
<form ng-submit="vm.onSubmit()" novalidate>
<formly-form model="vm.model" fields="vm.fields" form="vm.form">
<button type="submit" class="btn btn-primary submit-button">Submit</button>
</formly-form>
</form>
<hr />
<h2>Model</h2>
<pre>{{vm.model | json}}</pre>
<h2>Fields <small>(note, functions are not shown)</small></h2>
<pre>{{vm.originalFields | json}}</pre>
<h2>Form</h2>
<pre>{{vm.form | json}}</pre>
</div>
<div style="margin-top:30px">
<small>
This is an example for the
<a href="https://formly-js.github.io/angular-formly">angular-formly</a>
project made with ♥ by
<strong>
<span ng-if="!vm.author.name || !vm.author.url">
{{vm.author.name || 'anonymous'}}
</span>
<a ng-if="vm.author.url" ng-href="{{::vm.author.url}}">
{{vm.author.name}}
</a>
</strong>
<br />
This example is running angular version "{{vm.env.angularVersion}}" and formly version "{{vm.env.formlyVersion}}"
</small>
</div>
<script type="text/ng-template" id="repeatSection.html">
<div>
<!--loop through each element in model array-->
<div class="{{hideRepeat}}">
<div class="repeatsection" ng-repeat="element in model[options.key]" ng-init="fields = copyFields(to.fields)">
<formly-form fields="fields"
model="element"
bind-name="'formly_ng_repeat' + index + $parent.$index">
</formly-form>
<div style="margin-bottom:20px;">
<button type="button" class="btn btn-sm btn-danger" ng-click="model[options.key].splice($index, 1)">
Remove
</button>
</div>
<hr>
</div>
<p class="AddNewButton">
<button type="button" class="btn btn-primary" ng-click="addNew()" >{{to.btnText}}</button>
</p>
</div>
</script>
</body>
</html>
/* global angular */
(function() {
'use strict';
var app = angular.module('formlyExample', ['formly', 'formlyBootstrap'], function config(formlyConfigProvider) {
formlyConfigProvider.setType({
name: 'repeatSection',
templateUrl: 'repeatSection.html',
controller: function($scope) {
$scope.formOptions = {formState: $scope.formState};
$scope.addNew = addNew;
$scope.copyFields = copyFields;
function copyFields(fields) {
return angular.copy(fields);
}
function addNew() {
$scope.model[$scope.options.key] = $scope.model[$scope.options.key] || [];
var repeatsection = $scope.model[$scope.options.key];
var lastSection = repeatsection[repeatsection.length - 1];
var newsection = {};
repeatsection.push(newsection);
}
}
});
});
app.controller('MainCtrl', function MainCtrl(formlyVersion) {
var vm = this;
// funcation assignment
vm.onSubmit = onSubmit;
// variable assignment
vm.author = { // optionally fill in your info below :-)
name: 'Joe Zhou',
url: 'https://plus.google.com/u/0/111062476999618400219/posts' // a link to your twitter/github/blog/whatever
};
vm.exampleTitle = 'Repeating Section'; // add this
vm.env = {
angularVersion: angular.version.full,
formlyVersion: formlyVersion
};
init();
vm.originalFields = angular.copy(vm.fields);
// function definition
function onSubmit() {
alert(JSON.stringify(vm.model), null, 2);
}
function init() {
vm.model = {
max_points: 100,
grade_scheme_elements: [
{
course_id: 1,
id: 2,
level: "Pro",
low_range: 90,
letter: "A",
high_range: 100
},
{
course_id: 1,
id: 4,
level: "Cool",
low_range: 80,
letter: "B",
high_range: 89
},
{
course_id: 1,
id: 6,
level: "Jerk",
low_range: 70,
letter: "C",
high_range: 79
},
{
course_id: 1,
id: 8,
level: "lol",
low_range: 50,
letter: "D",
high_range: 60
}
]
}
vm.fields = [
{
type: 'repeatSection',
key: 'grade_scheme_elements',
templateOptions: {
btnText:'Add A Grade Level',
fields: [
{
className: 'row',
fieldGroup: [
{
className: 'col-xs-4',
type: 'input',
key: 'letter',
templateOptions: {
label: 'Letter Grade'
},
validators: {
input: {
expression: function(viewValue, modelValue) {
value = modelValue || viewValue;
return /^([ABCDEF][+-]?)$/.test(value);
},
message: '$viewValue + " is not a letter grade"'
}
}
},
{
type: 'input',
key: 'low_range',
className: 'col-xs-4',
templateOptions: {
label: 'Low Range'
}
},
{
type: 'input',
//want to bind this field to the previous index's low_range -1
key: 'high_range',
className: 'col-xs-4',
templateOptions: {
label: 'High Range',
disabled: true
}
}
]
}
]
}
}
];
}
});
})();
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |