<!DOCTYPE html>
<html ng-app="formlyExample">
<head>
<!-- Twitter bootstrap -->
<script data-require="lodash.js@*" data-semver="3.10.0" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" />
<!-- apiCheck is used by formly to validate its api -->
<script src="//npmcdn.com/api-check@latest/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.9/angular.js"></script>
<!-- Angular-UI Bootstrap has tabs directive we want -->
<script src="//npmcdn.com/angular-ui-bootstrap@latest/dist/ui-bootstrap-tpls.js"></script>
<!-- This is the latest version of formly core. -->
<script src="//npmcdn.com/angular-formly@latest/dist/formly.js"></script>
<!-- This is the latest version of formly bootstrap templates -->
<script src="//npmcdn.com/angular-formly-templates-bootstrap@latest/dist/angular-formly-templates-bootstrap.js"></script>
<script src="app.js"></script>
<title>Angular Formly Example</title>
</head>
<body class="container" ng-controller="mainCtrl as vm">
<div>
<h1>angular-formly example: {{vm.exampleTitle}}</h1>
<div>
This is a better example of how to use the
<a href="https://angular-ui.github.io/bootstrap/#/typeahead">UI Boostrap typeahead</a>
with angular-formly.
</div>
<hr />
<form novalidate="" name="vm.form" ng-submit="vm.onSubmit()">
<formly-form options="vm.options" fields="vm.fields" model="vm.model">
<button ng-disabled="vm.form.$invalid" class="btn btn-primary submit-button" type="submit">Submit</button>
<button ng-click="vm.options.resetModel()" class="btn btn-default" type="button">Reset</button>
</formly-form>
</form>
<hr />
<h2>Model Value</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-href="{{::vm.author.url}}" ng-if="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>
<!-- Put custom templates here -->
</body>
</html>
(function(angular) {
"use strict";
function initializer(formlyConfig) {
formlyConfig.setType({
name: "typeahead",
template: function(elem) {
var key;
if (elem.data.isArrayOfObjects && !elem.data.labelProp) {
key = "item[0]";
} else if (elem.data.isArrayOfObjects && elem.data.labelProp) {
key = "item[options.data.labelProp]";
} else {
key = "item";
}
var template = [
'<input type="text" ng-model="model[options.key]" typeahead-wait-ms="options.data.debounce" typeahead-select-on-blur="options.data.selectOnBlur" typeahead-focus-first="options.data.focusFirst" typeahead-min-length="options.data.minLength" typeahead-on-select="selectItemCallback($item, $model, $label, $event)"',
'uib-typeahead="item as ' + key + ' for item in to.options',
'| filter: filterBy($viewValue) | limitTo: options.data.limit" class="form-control">'
].join(" ");
return template;
},
wrapper: ["bootstrapLabel", "bootstrapHasError"],
defaultOptions: function(options) {
return {
data: {
limit: 10,
isArrayOfObjects: false,
labelProp: undefined,
filterOnlyByLabel: false,
selectOnBlur: false,
focusFirst: false,
debounce: 0,
minLength: 1,
onSelect: angular.noop
}
};
},
//The $filter service is not required. I used it only for some tests...
controller: ["$scope", "$filter", function($scope, $filter) {
var vm = $scope;
vm.filterBy = function(value) {
/*
* In order to filter based on a key we have to create an object type { key: $viewValue }
* in our particular case it is { State: $viewValue } but to make it generic it's necessary
* to add some logic and generate the object filter inside the controller.
* If the filterOnlyByLabel variable is false then we use the standard filter which applies
* the filter to the entire object.
*/
if (!vm.options.data.filterOnlyByLabel) return value;
var obj = {};
obj[vm.options.data.labelProp] = value;
return obj;
//Some interesting Tests using angular $filter service and lodash _.pluck
// var results = $filter('filter')(vm.to.options, obj);
// console.log("results: ", results);
// var results2 = _.pluck(results, vm.options.data.filterByProp);
// console.log("results2: ", results2);
};
vm.selectItemCallback = vm.options.data.onSelect;
}]
});
}
function mainCtrl(formlyVersion, USStates, $timeout, $http) {
var vm = this;
vm.onSubmit = onSubmit;
// variable assignment
vm.author = { // optionally fill in your info below :-)
name: "Marcelino Jorge Romero",
url: "http://tinyurl.com/marcelinojorgeromero"
};
vm.exampleTitle = 'UI Bootstrap Typeahead'; // add this
vm.env = {
angularVersion: angular.version.full,
formlyVersion: formlyVersion
};
vm.model = {};
vm.options = {};
vm.fields = [
{
key: "usstates",
type: "typeahead",
templateOptions: {
label: "State",
placeholder: "Start typing a US State...",
options: USStates
},
data: { //Override typeahead defaults (or add more data)
isArrayOfObjects: true,
filterOnlyByLabel: true,
labelProp: "State",
debounce: 500,
selectOnBlur: true,
focusFirst: true,
onSelect: function() {
console.log("onSelect overrided: ", arguments);
}
}
},
{
key: "asyncusstates",
type: "typeahead",
templateOptions: {
label: "State (Async load after 3 sec)",
placeholder: "This is Asynchronous load...",
options: []
},
expressionProperties: {
"templateOptions.options": function($viewValue, $modelValue, scope) {
return $timeout(function(){
console.log("states loaded asynchronously at " + new Date());
return USStates;
}, 3000);
}
},
data: { //Override typeahead defaults (or add more data)
isArrayOfObjects: true,
filterOnlyByLabel: true,
labelProp: "State",
debounce: 500,
selectOnBlur: true,
focusFirst: true,
onSelect: function() {
console.log("onSelect overrided: ", arguments);
}
}
},
{
key: "address",
type: "typeahead",
templateOptions: {
label: "Address",
placeholder: "This is Asynchronous load. Start typing a place...",
options: []
},
expressionProperties: {
"templateOptions.options": function($viewValue, $modelValue, scope) {
return $http.get("//maps.googleapis.com/maps/api/geocode/json", {
params: {
address: $viewValue,
sensor: false
}
}).then(function(response) {
return response.data.results.map(function(item) {
return item.formatted_address;
});
});
}
},
data: { //Override typeahead defaults (or add more data)
debounce: 500,
onSelect: function() {
console.log("onSelect overrided: ", arguments);
}
}
}
];
vm.originalFields = angular.copy(vm.fields);
// function definition
function onSubmit() {
vm.options.updateInitialValue();
alert(JSON.stringify(vm.model), null, 2);
}
}
mainCtrl.$inject = ["formlyVersion", "USStates", "$timeout", "$http"];
angular
.module("formlyExample", ["formly", "formlyBootstrap", "ui.bootstrap"])
.constant("USStates", [{Id:1 , State: "Alabama"}, {Id:2 , State: "Alaska"}, {Id:3 , State: "Arizona"}, {Id:4 , State: "Arkansas"}, {Id:5 , State: "California"}, {Id:6 , State: "Colorado"}, {Id:7 , State: "Connecticut"}, {Id:8 , State: "Delaware"}, {Id:9 , State: "Florida"}, {Id:10, State: "Georgia"}, {Id:11, State: "Hawaii"}, {Id:12, State: "Idaho"}, {Id:13, State: "Illinois"}, {Id:14, State: "Indiana"}, {Id:15, State: "Iowa"}, {Id:16, State: "Kansas"}, {Id:17, State: "Kentucky"}, {Id:18, State: "Louisiana"}, {Id:19, State: "Maine"}, {Id:20, State: "Maryland"}, {Id:21, State: "Massachusetts"}, {Id:22, State: "Michigan"}, {Id:23, State: "Minnesota"}, {Id:24, State: "Mississippi"}, {Id:25, State: "Missouri"}, {Id:26, State: "Montana"}, {Id:27, State: "Nebraska"}, {Id:28, State: "Nevada"}, {Id:29, State: "New Hampshire"}, {Id:30, State: "New Jersey"}, {Id:31, State: "New Mexico"}, {Id:32, State: "New York"}, {Id:33, State: "North Dakota"}, {Id:34, State: "North Carolina"}, {Id:35, State: "Ohio"}, {Id:36, State: "Oklahoma"}, {Id:37, State: "Oregon"}, {Id:38, State: "Pennsylvania"}, {Id:39, State: "Rhode Island"}, {Id:40, State: "South Carolina"}, {Id:41, State: "South Dakota"}, {Id:42, State: "Tennessee"}, {Id:43, State: "Texas"}, {Id:44, State: "Utah"}, {Id:45, State: "Vermont"}, {Id:46, State: "Virginia"}, {Id:47, State: "Washington"}, {Id:48, State: "West Virginia"}, {Id:49, State: "Wisconsin"}, {Id:50, State: "Wyoming"}])
.controller("mainCtrl", mainCtrl)
.run(initializer);
})(angular);