Skip to content
This repository has been archived by the owner on Apr 30, 2018. It is now read-only.

feat(formly-form): Use arrays for fieldTransforms #461

Merged
merged 1 commit into from
Sep 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions other/ERRORS_AND_WARNINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ of the expression, the scope you're passed wont have all the properties you may
See documentation [here](http://docs.angular-formly.com/docs/field-configuration-object#hideexpression-string--function)
and an example [here](http://angular-formly.com/#/example/field-options/hide-fields)

# FieldTransform as a function deprecated

To allow for plugin like functionality, `fieldTransform` functions on `formlyConfig.extras` and `formly-form.options`
are now deprecated. Moving forward fieldTransform will accept an array of `fieldTransform` functions. This makes it possible
to have multiple fieldTransforms. Note, `fieldTransform` functions will be removed in a major release.

# Notes

It is recommended to disable warnings in production using `formlyConfigProvider.disableWarnings = true`. Note: This will
Expand Down
38 changes: 32 additions & 6 deletions src/directives/formly-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,21 +133,47 @@ function formlyForm(formlyUsability, formlyWarn, $parse, formlyConfig, $interpol

function setupFields() {
$scope.fields = $scope.fields || [];
const fieldTransform = $scope.options.fieldTransform || formlyConfig.extras.fieldTransform;

if (fieldTransform) {
$scope.fields = fieldTransform($scope.fields, $scope.model, $scope.options, $scope.form);
if (!$scope.fields) {
throw formlyUsability.getFormlyError('fieldTransform must return an array of fields');
}
checkDeprecatedOptions($scope.options);

let fieldTransforms = $scope.options.fieldTransform || formlyConfig.extras.fieldTransform;

if (!angular.isArray(fieldTransforms)) {
fieldTransforms = [fieldTransforms];
}

angular.forEach(fieldTransforms, function transformFields(fieldTransform) {
if (fieldTransform) {
$scope.fields = fieldTransform($scope.fields, $scope.model, $scope.options, $scope.form);
if (!$scope.fields) {
throw formlyUsability.getFormlyError('fieldTransform must return an array of fields');
}
}
});

setupModels();

angular.forEach($scope.fields, attachKey); // attaches a key based on the index if a key isn't specified
angular.forEach($scope.fields, setupWatchers); // setup watchers for all fields
}

function checkDeprecatedOptions(options) {
if (formlyConfig.extras.fieldTransform && angular.isFunction(formlyConfig.extras.fieldTransform)) {
formlyWarn(
'fieldtransform-as-a-function-deprecated',
'fieldTransform as a function has been deprecated.',
`Attempted for formlyConfig.extras: ${formlyConfig.extras.fieldTransform.name}`,
formlyConfig.extras
);
} else if (options.fieldTransform && angular.isFunction(options.fieldTransform)) {
formlyWarn(
'fieldtransform-as-a-function-deprecated',
'fieldTransform as a function has been deprecated.',
`Attempted for form`,
options
);
}
}

function setupOptions() {
formlyApiCheck.throw(
Expand Down
43 changes: 42 additions & 1 deletion src/directives/formly-form.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import testUtils from '../test.utils.js';
import angular from 'angular-fix';
import _ from 'lodash';

const {getNewField, input, basicForm} = testUtils;
const {getNewField, input, basicForm, shouldWarnWithLog} = testUtils;

describe('formly-form', () => {
let $compile, formlyConfig, scope, el, $timeout;
Expand Down Expand Up @@ -759,6 +759,33 @@ describe('formly-form', () => {
formlyConfig.extras.fieldTransform = fieldTransform;
});

it(`should give a deprecation warning when formlyConfig.extras.fieldTransform is a function rather than an array`, inject(($log) => {
shouldWarnWithLog(
$log,
[
'Formly Warning:',
'fieldTransform as a function has been deprecated.',
/Attempted for formlyConfig.extras/
],
compileAndDigest
);
}));

it(`should give a deprecation warning when options.fieldTransform function rather than an array`, inject(($log) => {
formlyConfig.extras.fieldTransform = undefined;
scope.fields = [getNewField()];
scope.options.fieldTransform = fields => fields;
shouldWarnWithLog(
$log,
[
'Formly Warning:',
'fieldTransform as a function has been deprecated.',
'Attempted for form'
],
compileAndDigest
);
}));

it(`should throw an error if something is passed in and nothing is returned`, () => {
scope.fields = [getNewField()];
scope.options.fieldTransform = function() {
Expand All @@ -778,6 +805,20 @@ describe('formly-form', () => {
doExpectations(spy);
});

it(`should allow you to use an array of transform functions`, () => {
scope.fields = [getNewField({
customThing: 'foo',
otherCustomThing: {
whatever: '|-o-|'
}})];
scope.options.fieldTransform = [fieldTransform];
expect(() => compileAndDigest()).to.not.throw();

const field = scope.fields[0];
expect(field).to.have.deep.property('data.customThing');
expect(field).to.have.deep.property('data.otherCustomThing');
});

function doExpectations(spy) {
const originalFields = [{
key: 'keyProp',
Expand Down
5 changes: 3 additions & 2 deletions src/providers/formlyApiCheck.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,16 @@ const fieldOptionsApiShape = {

const formlyFieldOptions = apiCheck.shape(fieldOptionsApiShape).strict;


const formOptionsApi = apiCheck.shape({
formState: apiCheck.object.optional,
resetModel: apiCheck.func.optional,
updateInitialValue: apiCheck.func.optional,
removeChromeAutoComplete: apiCheck.bool.optional,
templateManipulators: templateManipulators.optional,
wrapper: specifyWrapperType.optional,
fieldTransform: apiCheck.func.optional,
fieldTransform: apiCheck.oneOfType([
apiCheck.func, apiCheck.array
]).optional,
data: apiCheck.object.optional
}).strict;

Expand Down