-
Notifications
You must be signed in to change notification settings - Fork 725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFR] All fields have template #713
Merged
Merged
Changes from 13 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
d5fff29
Add support for .template() to all field types
fzaninotto 2b31ad3
Handle template for filters
fzaninotto 8cc18a8
use compatible admin-config version
fzaninotto be18f4d
Fix tests
fzaninotto 7fd429b
Add test for maField
fzaninotto 15279e1
Add unit tests for maColumn and maFilter
fzaninotto 70c88f2
Add doc, make `value` always available in scope for template
fzaninotto cfc389f
Explicit template type deprecation
fzaninotto 379e3c5
Siplify fieldView configuration now that `value` is in every scope
fzaninotto 463112e
Fix typo
fzaninotto 5ea24c7
Fix bugs
fzaninotto 1558661
Fix more bugs
fzaninotto edabd09
Fix validation bug
fzaninotto 3d6f5b5
Fix typo
fzaninotto e09bd7c
Fix typos
fzaninotto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Upgrade to 0.9 | ||
|
||
## All fields have `.template()` | ||
|
||
All field types now support the `template()` method, which makes it easy to customize the look and feel of a particular field, withut sacrificing the native features. | ||
|
||
For instance, if you want to customize the appearance of a `NumberField` according to its value: | ||
|
||
```js | ||
listview.fields([ | ||
nga.field('amount', 'number') | ||
.format('$0,000.00') | ||
.template('<span ng-class="{ \'red\': value < 0 }"><ma-number-column field="::field" value="::entry.values[field.name()]"></ma-number-column></span>') | ||
]); | ||
``` | ||
|
||
This removes the need for [custom types](doc/Custom-types.md) in a vast majority of cases. | ||
|
||
The `template` *field type* is deprecated and will be removed in future versions. Simply use the default field type together with the `template()` method instead: | ||
|
||
```js | ||
// before | ||
nga.field('name', 'template').template('{{ entry.values.name }}') | ||
// now | ||
nga.field('name').template('{{ entry.values.name }}') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ application | |
|-transform | ||
|-attributes | ||
|-cssClasses | ||
|-template | ||
|-validation | ||
|-editable | ||
``` | ||
|
@@ -283,10 +284,10 @@ Add filters to the list. Each field maps a property in the API endpoint result. | |
nga.field('q').label('Search').pinned(true) | ||
]); | ||
|
||
Filter fields can be of any type, including `reference` and `template`. This allows to define custom filters with ease. | ||
Filter fields can be of any type, including `reference`. This allows to define custom filters with ease. | ||
|
||
listView.filters([ | ||
nga.field('q', 'template').label('') | ||
nga.field('q').label('') | ||
.template('<div class="input-group"><input type="text" ng-model="value" placeholder="Search" class="form-control"></input><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span></div>'), | ||
]); | ||
|
||
|
@@ -379,12 +380,11 @@ A field is the representation of a property of an entity. | |
* [`reference` Field Type](#reference-field-type) | ||
* [`referenced_list` Field Type](#referenced_list-field-type) | ||
* [`reference_many` Field Type](#reference_many-field-type) | ||
* [`template` Field Type](#template-field-type) | ||
|
||
### General Field Settings | ||
|
||
* `nga.field(name, type)` | ||
Create a new field of the given type. Default type is 'string', so you can omit it. Bundled types include `string`, `text`, `wysiwyg`, `password`, `email`, `date`, `datetime`, `number`, `float`, `boolean`, `choice`, `choices`, `json`, `file`, `reference`, `reference_list`, `reference_many`, and `template`. | ||
Create a new field of the given type. Default type is 'string', so you can omit it. Bundled types include `string`, `text`, `wysiwyg`, `password`, `email`, `date`, `datetime`, `number`, `float`, `boolean`, `choice`, `choices`, `json`, `file`, `reference`, `reference_list`, and `reference_many`. | ||
|
||
* `label(string label)` | ||
Define the label of the field. Defaults to the uppercased field name. | ||
|
@@ -466,6 +466,25 @@ A list of CSS classes to be added to the corresponding field. If you provide a f | |
return 'my-custom-css-class-for-list-header'; | ||
}); | ||
|
||
* `template(String|Function)` | ||
All field types support the `template()` method, which makes it easy to customize the look and feel of a particular field, withut sacrificing the native features. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. without |
||
|
||
For instance, if you want to customize the appearance of a `NumberField` according to its value: | ||
|
||
listview.fields([ | ||
nga.field('amount', 'number') | ||
.format('$0,000.00') | ||
.template('<span ng-class="{ \'red\': value < 0 }"><ma-number-column field="::field" value="::entry.values[field.name()]"></ma-number-column></span>') | ||
]); | ||
|
||
The template scope exposes the following variables: | ||
|
||
- `value`, `field`, `entry`, `entity`, and `datastore` in `listView` and `showView` | ||
- `value`, `field`, `values`, and `datastore` in filters | ||
- `value`, `field`, `entry`, `entity`, `form`, and `datastore` in `editionView` and `creationView` | ||
|
||
Most of the time, `template()` is used to customize the existing ng-admin directives (like `ma-number-column>` in the previous example), for instance by decorating them. If you want to learn about these native directives, explore the [column](../src/javascripts/ng-admin/crud/column), [field](../src/javascripts/ng-admin/crud/field), and [fieldView](../src/javascripts/ng-admin/crud/fieldView) directories in ng-admin source. | ||
|
||
* `defaultValue(*)` | ||
Define the default value of the field in the creation form. | ||
|
||
|
@@ -765,8 +784,3 @@ If set to false, all references (in the limit of `perPage` parameter) would be r | |
}) | ||
.perPage(10) // limit the number of results to 10 | ||
]); | ||
|
||
### `template` Field Type | ||
|
||
* `template(*)` | ||
Define the template to be displayed for fields of type `template` (can be a string or a function). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,9 +32,31 @@ myEntity.listView().fields([ | |
]); | ||
``` | ||
|
||
## Customizing The Template For A Given Field | ||
|
||
All field types support the `template()` method, which makes it easy to customize the look and feel of a particular field, withut sacrificing the native features. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. without |
||
|
||
For instance, if you want to customize the appearance of a `NumberField` according to its value: | ||
|
||
```js | ||
listview.fields([ | ||
nga.field('amount', 'number') | ||
.format('$0,000.00') | ||
.template('<span ng-class="{ \'red\': value < 0 }"><ma-number-column field="::field" value="::entry.values[field.name()]"></ma-number-column></span>') | ||
]); | ||
``` | ||
|
||
The template scope exposes the following variables: | ||
|
||
* `value`, `field`, `entry`, `entity`, and `datastore` in `listView` and `showView` | ||
* `value`, `field`, `values`, and `datastore` in filters | ||
* `value`, `field`, `entry`, `entity`, `form`, and `datastore` in `editionView` and `creationView` | ||
|
||
Most of the time, `template()` is used to customize the existing ng-admin directives (like `ma-number-column>` in the previous example), for instance by decorating them. If you want to learn about these native directives, explore the [column](../src/javascripts/ng-admin/crud/column), [field](../src/javascripts/ng-admin/crud/field), and [fieldView](../src/javascripts/ng-admin/crud/fieldView) directories in ng-admin source. | ||
|
||
## Customizing Directives Templates | ||
|
||
Using Angular's [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, and the ability to decorate another provider, you can customize the templates of all the directives used by ng-admin. Here is an example of customization of the 'text' input field customization: | ||
Using Angular's [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, and the ability to decorate another provider, you can customize the template of any directive used by ng-admin for your entire application. Here is an example of customization of the 'text' input field: | ||
|
||
```js | ||
var myApp = angular.module('myApp', ['ng-admin']); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,77 @@ | ||
/*global define*/ | ||
function maColumn($state, $anchorScroll, $compile, Configuration, FieldViewConfiguration) { | ||
|
||
define(function (require) { | ||
'use strict'; | ||
|
||
function maColumn($state, $anchorScroll, $compile, Configuration, FieldViewConfiguration) { | ||
|
||
function getDetailLinkRouteName(field, entity) { | ||
if (entity.isReadOnly) { | ||
return entity.showView().enabled ? 'show' : false; | ||
} | ||
if (field.detailLinkRoute() == 'edit' && entity.editionView().enabled) { | ||
return 'edit'; | ||
} | ||
function getDetailLinkRouteName(field, entity) { | ||
if (entity.isReadOnly) { | ||
return entity.showView().enabled ? 'show' : false; | ||
} | ||
if (field.detailLinkRoute() == 'edit' && entity.editionView().enabled) { | ||
return 'edit'; | ||
} | ||
return entity.showView().enabled ? 'show' : false; | ||
} | ||
|
||
function isDetailLink(field, entity) { | ||
if (field.isDetailLink() === false) { | ||
function isDetailLink(field, entity) { | ||
if (field.isDetailLink() === false) { | ||
return false; | ||
} | ||
if (field.type() == 'reference' || field.type() == 'reference_many') { | ||
var relatedEntity = Configuration().getEntity(field.targetEntity().name()); | ||
if (!relatedEntity) { | ||
return false; | ||
} | ||
if (field.type() == 'reference' || field.type() == 'reference_many') { | ||
var relatedEntity = Configuration().getEntity(field.targetEntity().name()); | ||
if (!relatedEntity) { | ||
return false; | ||
} | ||
return getDetailLinkRouteName(field, relatedEntity) !== false; | ||
} | ||
return getDetailLinkRouteName(field, entity) !== false; | ||
return getDetailLinkRouteName(field, relatedEntity) !== false; | ||
} | ||
return getDetailLinkRouteName(field, entity) !== false; | ||
} | ||
|
||
return { | ||
restrict: 'E', | ||
scope: { | ||
field: '&', | ||
entry: '&', | ||
entity: '&', | ||
datastore: '&' | ||
}, | ||
link: function(scope, element) { | ||
scope.datastore = scope.datastore(); | ||
scope.field = scope.field(); | ||
scope.entry = scope.entry(); | ||
scope.entity = scope.entity(); | ||
var type = scope.field.type(); | ||
return { | ||
restrict: 'E', | ||
scope: { | ||
field: '&', | ||
entry: '&', | ||
entity: '&', | ||
datastore: '&' | ||
}, | ||
link: function(scope, element) { | ||
scope.datastore = scope.datastore(); | ||
scope.field = scope.field(); | ||
scope.entry = scope.entry(); | ||
scope.value = scope.entry.values[scope.field.name()]; | ||
scope.entity = scope.entity(); | ||
let customTemplate = scope.field.getTemplateValue(scope.entry); | ||
if (customTemplate) { | ||
element.append(customTemplate); | ||
} else { | ||
let type = scope.field.type(); | ||
if (isDetailLink(scope.field, scope.entity)) { | ||
element.append(FieldViewConfiguration[type].getLinkWidget()); | ||
} else { | ||
element.append(FieldViewConfiguration[type].getReadWidget()); | ||
} | ||
$compile(element.contents())(scope); | ||
scope.gotoDetail = function () { | ||
var route = getDetailLinkRouteName(scope.field, scope.entity); | ||
$state.go($state.get(route), | ||
angular.extend({}, $state.params, { | ||
entity: scope.entry.entityName, | ||
id: scope.entry.identifierValue | ||
})); | ||
}; | ||
scope.gotoReference = function () { | ||
var referenceEntity = scope.field.targetEntity().name(); | ||
var relatedEntity = Configuration().getEntity(referenceEntity); | ||
var referenceId = scope.entry.values[scope.field.name()]; | ||
var route = getDetailLinkRouteName(scope.field, relatedEntity); | ||
$state.go($state.get(route), { | ||
entity: referenceEntity, | ||
id: referenceId | ||
}); | ||
}; | ||
} | ||
}; | ||
} | ||
$compile(element.contents())(scope); | ||
scope.gotoDetail = function () { | ||
var route = getDetailLinkRouteName(scope.field, scope.entity); | ||
$state.go($state.get(route), | ||
angular.extend({}, $state.params, { | ||
entity: scope.entry.entityName, | ||
id: scope.entry.identifierValue | ||
})); | ||
}; | ||
scope.gotoReference = function () { | ||
var referenceEntity = scope.field.targetEntity().name(); | ||
var relatedEntity = Configuration().getEntity(referenceEntity); | ||
var referenceId = scope.entry.values[scope.field.name()]; | ||
var route = getDetailLinkRouteName(scope.field, relatedEntity); | ||
$state.go($state.get(route), { | ||
entity: referenceEntity, | ||
id: referenceId | ||
}); | ||
}; | ||
} | ||
}; | ||
} | ||
|
||
maColumn.$inject = ['$state', '$anchorScroll', '$compile', 'NgAdminConfiguration', 'FieldViewConfiguration']; | ||
maColumn.$inject = ['$state', '$anchorScroll', '$compile', 'NgAdminConfiguration', 'FieldViewConfiguration']; | ||
|
||
return maColumn; | ||
}); | ||
module.exports = maColumn; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
without