diff --git a/README.md b/README.md index 582c7ca3..23ccc921 100644 --- a/README.md +++ b/README.md @@ -377,8 +377,11 @@ Define the default value of the field in the creation form. ### `number` Field Settings -* `fractionSize(integer)` -Number of decimal places to round the number to. If this is not provided, then the fraction size is computed from the current locale's number formatting pattern. +* `format(string)` +Format for number to string conversion. Based on [Numeral.js](http://numeraljs.com/), which uses a syntax similar to Excel. You can configure the locale and create named formats by following [angular-numeraljs](https://github.com/baumandm/angular-numeraljs) instructions. + + nga.field('cost', 'number').format('$0,0.00'); + // now 1234.5 will render as '$1,234.50' ### `choice` and `choices` Field Settings diff --git a/bower.json b/bower.json index 49340be8..018cb768 100644 --- a/bower.json +++ b/bower.json @@ -8,26 +8,27 @@ "dependencies": { "angular": "~1.3.1", "angular-bootstrap": "~0.12.0", - "angular-resource": "~1.3.1", "angular-cookies": "~1.3.1", + "angular-numeraljs": "~1.1.6", + "angular-resource": "~1.3.1", "angular-sanitize": "~1.3.1", - "json3": "~3.2.6", - "es5-shim": "~3.4.0", - "jquery": "~1.11.0", - "requirejs": "~2.1.14", - "requirejs-text": "~2.0.12", - "bootstrap-sass-official": "~3.3.0", - "restangular": "~1.4.0", + "angular-ui-codemirror": "~0.2.2", "angular-ui-router": "~0.2.13", "bootstrap": "~3.3.1", + "bootstrap-sass-official": "~3.3.0", + "es5-shim": "~3.4.0", "fontawesome": "~4.1.0", "humane": "~3.2.0", - "nprogress": "~0.1.6", - "textAngular": "~1.2.2", - "ngInflection": "~1.0.0", - "angular-ui-codemirror": "~0.2.2", + "jquery": "~1.11.0", + "json3": "~3.2.6", "jsonlint": "~1.6.0", - "ng-file-upload": "~2.2.2" + "ng-file-upload": "~2.2.2", + "ngInflection": "~1.0.0", + "nprogress": "~0.1.6", + "requirejs": "~2.1.14", + "requirejs-text": "~2.0.12", + "restangular": "~1.4.0", + "textAngular": "~1.2.2" }, "devDependencies": { "angular-mocks": "~1.3.1", diff --git a/src/javascripts/ng-admin.js b/src/javascripts/ng-admin.js index 30fb69c5..edf6419d 100644 --- a/src/javascripts/ng-admin.js +++ b/src/javascripts/ng-admin.js @@ -8,23 +8,25 @@ define('angular', [], function () { require.config({ paths: { + 'angular-bootstrap': 'bower_components/angular-bootstrap/ui-bootstrap.min', + 'angular-bootstrap-tpls': 'bower_components/angular-bootstrap/ui-bootstrap-tpls.min', + 'angular-numeraljs': 'bower_components/angular-numeraljs/dist/angular-numeraljs', 'angular-resource': 'bower_components/angular-resource/angular-resource', 'angular-sanitize': 'bower_components/angular-sanitize/angular-sanitize', + 'angular-ui-codemirror': 'bower_components/angular-ui-codemirror/ui-codemirror.min', 'angular-ui-router': 'bower_components/angular-ui-router/release/angular-ui-router', - 'ng-file-upload': 'bower_components/ng-file-upload/angular-file-upload', + 'humane': 'bower_components/humane/humane', + 'inflection': 'bower_components/inflection/inflection.min', 'lodash': 'bower_components/lodash/dist/lodash.min', - 'text' : 'bower_components/requirejs-text/text', - 'angular-bootstrap': 'bower_components/angular-bootstrap/ui-bootstrap.min', - 'angular-bootstrap-tpls': 'bower_components/angular-bootstrap/ui-bootstrap-tpls.min', - 'restangular': 'bower_components/restangular/dist/restangular', + 'ng-file-upload': 'bower_components/ng-file-upload/angular-file-upload', 'ngInflection': 'bower_components/ngInflection/ngInflection', - 'inflection': 'bower_components/inflection/inflection.min', - 'humane': 'bower_components/humane/humane', 'nprogress': 'bower_components/nprogress/nprogress', + 'numeral': 'bower_components/numeral/numeral', + 'restangular': 'bower_components/restangular/dist/restangular', + 'text' : 'bower_components/requirejs-text/text', 'textangular': 'bower_components/textAngular/dist/textAngular.min', - 'angular-ui-codemirror': 'bower_components/angular-ui-codemirror/ui-codemirror.min', - 'MainModule': 'ng-admin/Main/MainModule', 'CrudModule': 'ng-admin/Crud/CrudModule', + 'MainModule': 'ng-admin/Main/MainModule', 'AdminDescription': '../../build/ng-admin-configuration' }, shim: { diff --git a/src/javascripts/ng-admin/Crud/CrudModule.js b/src/javascripts/ng-admin/Crud/CrudModule.js index aab793dc..3a90f9ce 100644 --- a/src/javascripts/ng-admin/Crud/CrudModule.js +++ b/src/javascripts/ng-admin/Crud/CrudModule.js @@ -5,6 +5,7 @@ define(function (require) { var angular = require('angular'); inflection = require('inflection'); + var numeral = require('numeral'); require('angular-ui-router'); require('angular-sanitize'); @@ -13,9 +14,10 @@ define(function (require) { require('textangular'); require('ngInflection'); require('angular-ui-codemirror'); + require('angular-numeraljs'); var CrudModule = angular.module('crud', [ - 'ui.router', 'ui.bootstrap', 'ngSanitize', 'textAngular', 'ngInflection', 'ui.codemirror', 'angularFileUpload' + 'ui.router', 'ui.bootstrap', 'ngSanitize', 'textAngular', 'ngInflection', 'ui.codemirror', 'angularFileUpload', 'ngNumeraljs' ]); CrudModule.controller('ListController', require('ng-admin/Crud/list/ListController')); diff --git a/src/javascripts/ng-admin/Crud/column/maNumberColumn.js b/src/javascripts/ng-admin/Crud/column/maNumberColumn.js index 2fea3b76..a73693cb 100644 --- a/src/javascripts/ng-admin/Crud/column/maNumberColumn.js +++ b/src/javascripts/ng-admin/Crud/column/maNumberColumn.js @@ -10,7 +10,7 @@ define(function (require) { value: '&', field: '&' }, - template: '{{ value() | number:field().format() }}' + template: '{{ value() | numeraljs:field().format() }}' }; } diff --git a/src/javascripts/ng-admin/es6/lib/Field/NumberField.js b/src/javascripts/ng-admin/es6/lib/Field/NumberField.js index b214d0bb..84285ac2 100644 --- a/src/javascripts/ng-admin/es6/lib/Field/NumberField.js +++ b/src/javascripts/ng-admin/es6/lib/Field/NumberField.js @@ -4,23 +4,32 @@ class NumberField extends Field { constructor(name) { super(name); this._type = "number"; - this._fractionSize = undefined; + this._format = undefined; } /** - * Number of decimal places to round the number to. If this is not provided, - * then the fraction size is computed from the current locale's number formatting pattern. - * In the case of the default locale, it will be 3. + * Specify format pattern for number to string conversion. * + * Based on NumeralJs, which uses a syntax similar to Excel. + * + * {@link} http://numeraljs.com/ + * {@link} https://github.com/baumandm/angular-numeraljs * {@example} * - * nga.field('height', 'number').fractionSize(2); + * nga.field('height', 'number').format('$0,0.00'); */ - fractionSize(value) { - if (!arguments.length) return this._fractionSize; - this._fractionSize = value; + format(value) { + if (!arguments.length) return this._format; + this._format = value; + return this; + } + + fractionSize(decimals) { + console.warn('NumberField.fractionSize() is deprecated, use NumberField.format() instead'); + this.format('0.' + '0'.repeat(decimals)); return this; - }; + } + } export default NumberField; diff --git a/src/javascripts/test/app-test.js b/src/javascripts/test/app-test.js index 74e3da6b..865f1062 100644 --- a/src/javascripts/test/app-test.js +++ b/src/javascripts/test/app-test.js @@ -22,17 +22,19 @@ requirejs.config({ 'mock/Restangular': '/base/test/mock/Restangular', 'angular': 'bower_components/angular/angular', + 'angular-bootstrap': 'bower_components/angular-bootstrap/ui-bootstrap.min', + 'angular-bootstrap-tpls': 'bower_components/angular-bootstrap/ui-bootstrap-tpls.min', + 'angular-numeraljs': 'bower_components/angular-numeraljs/dist/angular-numeraljs', 'angular-resource': 'bower_components/angular-resource/angular-resource', - 'angular-sanitize': 'bower_components/angular-sanitize/angular-sanitize', 'angular-route': 'bower_components/angular-route/angular-route', + 'angular-sanitize': 'bower_components/angular-sanitize/angular-sanitize', 'angular-ui-router': 'bower_components/angular-ui-router/release/angular-ui-router', - 'lodash': 'bower_components/lodash/dist/lodash.min', - 'text' : 'bower_components/requirejs-text/text', - 'angular-bootstrap': 'bower_components/angular-bootstrap/ui-bootstrap.min', - 'angular-bootstrap-tpls': 'bower_components/angular-bootstrap/ui-bootstrap-tpls.min', - 'restangular': 'bower_components/restangular/dist/restangular', 'humane': 'bower_components/humane/humane', + 'lodash': 'bower_components/lodash/dist/lodash.min', 'nprogress': 'bower_components/nprogress/nprogress', + 'numeral': 'bower_components/numeral/numeral', + 'restangular': 'bower_components/restangular/dist/restangular', + 'text' : 'bower_components/requirejs-text/text', 'MainModule': 'ng-admin/Main/MainModule', 'CrudModule': 'ng-admin/Crud/CrudModule' @@ -41,6 +43,9 @@ requirejs.config({ 'angular': { exports: 'angular' }, + 'angular-numeraljs': { + deps: ['angular'] + }, 'angular-mocks': { deps: ['angular'] }, @@ -70,6 +75,9 @@ requirejs.config({ }, 'nprogress': { exports: 'NProgress' + }, + 'numeral': { + exports: 'numeral' } }, diff --git a/src/javascripts/test/karma.conf.js b/src/javascripts/test/karma.conf.js index 629be34f..eb7929c9 100644 --- a/src/javascripts/test/karma.conf.js +++ b/src/javascripts/test/karma.conf.js @@ -7,30 +7,31 @@ module.exports = function (config) { plugins: ['karma-requirejs', 'karma-jasmine', 'karma-chrome-launcher', 'karma-phantomjs-launcher', 'karma-babel-preprocessor'], files: [ - {pattern: 'bower_components/requirejs-text/text.js', included: false}, - {pattern: 'bower_components/requirejs-text/text.js', included: false}, - {pattern: 'bower_components/codemirror/lib/codemirror.js', included: false}, + {pattern: 'bower_components/angular-mocks/angular-mocks.js', included: false}, + {pattern: 'bower_components/angular-numeraljs/dist/angular-numeraljs.js', included: false}, + {pattern: 'bower_components/angular/angular.js', included: false}, {pattern: 'bower_components/codemirror/addon/edit/closebrackets.js', included: false}, {pattern: 'bower_components/codemirror/addon/edit/matchbrackets.js', included: false}, - {pattern: 'bower_components/codemirror/addon/lint/lint.js', included: false}, - {pattern: 'bower_components/jsonlint/lib/jsonlint.js', included: false}, {pattern: 'bower_components/codemirror/addon/lint/json-lint.js', included: false}, + {pattern: 'bower_components/codemirror/addon/lint/lint.js', included: false}, {pattern: 'bower_components/codemirror/addon/selection/active-line.js', included: false}, + {pattern: 'bower_components/codemirror/lib/codemirror.js', included: false}, {pattern: 'bower_components/codemirror/mode/javascript/javascript.js', included: false}, - {pattern: 'bower_components/angular/angular.js', included: false}, - {pattern: 'bower_components/angular-mocks/angular-mocks.js', included: false}, - {pattern: 'ng-admin/lib/polyfill/bind.js', included: true}, + {pattern: 'bower_components/jsonlint/lib/jsonlint.js', included: false}, + {pattern: 'bower_components/numeral/numeral.js', included: false}, + {pattern: 'bower_components/requirejs-text/text.js', included: false}, // ng-admin application files - {pattern: 'ng-admin/es6/lib/**/*.js', included: false}, {pattern: 'ng-admin/**/**/**/*.js', included: false}, - {pattern: 'ng-admin/lib/**/*.js', included: false}, - {pattern: 'ng-admin/**/view/**/*.html', included: false}, {pattern: 'ng-admin/**/*/*.html', included: false}, + {pattern: 'ng-admin/**/view/**/*.html', included: false}, + {pattern: 'ng-admin/es6/lib/**/*.js', included: false}, + {pattern: 'ng-admin/lib/**/*.js', included: false}, + {pattern: 'ng-admin/lib/polyfill/bind.js', included: true}, // Test files - {pattern: 'test/unit/**/**/*.js', included: false}, {pattern: 'test/mock/*.js', included: false}, + {pattern: 'test/unit/**/**/*.js', included: false}, // Test bootstrap 'test/app-test.js' diff --git a/src/javascripts/test/unit/Crud/column/maNumberColumnSpec.js b/src/javascripts/test/unit/Crud/column/maNumberColumnSpec.js new file mode 100644 index 00000000..f7ecf59e --- /dev/null +++ b/src/javascripts/test/unit/Crud/column/maNumberColumnSpec.js @@ -0,0 +1,51 @@ +/*global define,angular,inject,describe,it,expect,beforeEach*/ + +define(function (require) { + 'use strict'; + + describe('directive: ma-number-column', function () { + var directive = require('ng-admin/Crud/column/maNumberColumn'); + var NumberField = require('ng-admin/es6/lib/Field/NumberField'); + angular.module('testapp_NumberColumn', ['ngNumeraljs']).directive('maNumberColumn', directive); + require('angular-mocks'); + require('numeral'); + require('angular-numeraljs'); + + var $compile, + scope, + directiveUsage = ''; + + beforeEach(module('testapp_NumberColumn')); + + beforeEach(inject(function (_$compile_, _$rootScope_) { + $compile = _$compile_; + scope = _$rootScope_; + })); + + it("should contain a span tag", function () { + scope.field = new NumberField(); + var element = $compile(directiveUsage)(scope); + scope.$digest(); + expect(element.children()[0].nodeName).toBe('SPAN'); + }); + + it("should contain the bounded value with", function () { + scope.field = new NumberField(); + scope.value = 123; + var element = $compile(directiveUsage)(scope); + scope.$digest(); + expect(element.find('span').html()).toBe('123'); + scope.value = 456; + scope.$digest(); + expect(element.find('span').html()).toBe('456'); + }); + + it("should use the provided number format", function () { + scope.field = new NumberField().format('$0,000.00'); + scope.value = 1234.5; + var element = $compile(directiveUsage)(scope); + scope.$digest(); + expect(element.find('span').html()).toBe('$1,234.50'); + }); + }); +});