Typrod (acronym of "type", "property" and "data"; and abbreviated as TPD) is an AngularJS library to automate and synthetize data handling based on:
- templates and
- value conversions.
By NPM or with CDN embeds:
npm install typrod
Then import TPD and add it as a dependency:
angular.module('myApp', [require('typrod')]);
<script src="https://unpkg.com/angular@1.8.3/angular.js"></script>
<script src="https://unpkg.com/jquery@3.6.1"></script>
<script src="https://unpkg.com/specificity@0.4.1"></script>
<script src="https://unpkg.com/lodash@4.17.21"></script>
<script src="https://unpkg.com/typrod/dist/typrod.js"></script>
angular.module('myApp', ['tpd']);
Register, in a controller, this array with such object...
$scope.data = [
{
name: 'sentence',
type: 'string',
label: 'Sentence'
}
];
... and bind it to a form in this way:
<form tpd-data="data"></form>
An <input>
(next to its own associated <label>
) and a submit <button>
are rendered within.
Now add another two similar items as:
label: 'Sentence'
- }
+ },
+ {
+ name: 'startDay',
+ type: 'date',
+ label: 'Start day'
+ },
+ {
+ name: 'isOk',
+ type: 'boolean',
+ label: 'It\'s okay?'
+ }
];
It finally results:
<form>
<div>
<label for="sentence">Sentence</label>
<input type="text" id="sentence">
</div>
<div>
<label for="startDay">Start day</label>
<input type="date" id="startDay">
</div>
<div><label><input type="checkbox"> It's okay?</label></div>
<button>Submit</button>
</form>
Well, you are taking built the visual montage, nice, but you cannot manage the logic yet. To achieve it, you must to use a 2nd attribute...
- <form tpd-data="data"></form>
+ <form tpd-data="data" tpd-values="values"></form>
... with an object like:
{
sentence: 'Hello, world!',
startDay: '2021-09-13',
isOk: true
}
(It is important that each property key matches the previous name
).
Change the form controls and the values object will be modified too. Also notice that unexpectedly the date value used in the view is not really a string but a instance of Date
. There is a two-way transformation.
It looks some needy to get styles, right? No problem! Load your favorite CSS framework and adjust the composed HTML using the API.
- Here are some words that may create confusion since also are elemental terms of JavaScript, AngularJS, CSS or even SQL. Because of this, for avoid ambiguity, our own concepts will be explicitly designated (e.g. "TPD data").
- We will take the previous examples to show samples.
- This information is very useful: All of these terms will be named later.
[ // TPD data
{ // TPD property
name: 'sentence',
type: 'string', // TPD type
label: 'Sentence'
},
// ...
];
Determines the kind of info. It can be whatever you can think. No limits.
This is each of instances of a certain TPD type (and other several fits) whose a double TPD values are part of.
Grouping of TPD properties.
{ // TPD JSON values
sentence: 'Hello, world!',
startDay: '2021-09-13',
isOk: true
}
{ // TPD formatted values
// ...
startDay: new Date('2021-09-13'),
// ...
}
Handled in conversions whose two kinds are:
Original values arranged in JSON.
Transformed (if is needed) from aforesaid and gave back too (cyclic process).
<form><!-- TPD component -->
<!-- TPD content -->
<div><!-- TPD container -->
<label for="...">...</label>
<input type="text" id="...">
</div>
...
<div><label><input type="checkbox"> ...</label></div><!-- ETC -->
<button>Submit</button>
<!-- End of TPD content -->
</form>
Any tag with any classname, attribute, parent...
Full internal HTML included in TPD components; concatenation of TPD container and extra elements.
The repeated tags, corresponding each to a TPD property, that contains an appropriate HTML content.
It may happen that, for a concrete TPD component, we find a particular TPD type which is not structured than regularly.
We know it as exceptional TPD container (ETC).
Why to use Typrod?:
- Code extremely simplified. On the principle of "Write less, do more".
- Clear distinction between representation (HTML structure, class names, styles, etc.) and logical (what kind of data is it, param name, labelling, requirement, etc.). And in consequence:
- Centralization. Full logics are dumped into controllers, not also partially in its views.
- Abstraction of core data, assuming that TPD properties can share homologous behaviours.
- More maintainable and reliable source code.
- Integrated reutilization of mechanisms.
- Uniformity, homogeneity and consistency.
- Possible human mistakes avoided on bad-writing, forgetting...
- Easy and fast to migrate CSS frameworks.
- Unlimited customization. Not adaptive to any particular CSS dependencies.
- Well-known system, not new or weird:
- Specifications of TPD data are similar to databases', like in SQL table creations (column name, datatype, mandatory...).
- Use of a worldwide standard data-interchange format such as JSON.
- TPD components are descripted by CSS syntax.
- Flexibility, adaptability and variety on function arguments and data types.
Typrod sets and gets by a provider and a service.
It is named tpdProvider
, whose methods (of which the setters and deleters return it, allowing chaining) are:
Sets a TPD type.
Param | Type | Details |
---|---|---|
name | String | Name. The '*' is reserved to apply globally. |
opts | Object | Options. |
Function | To overwrite:
| |
Array | To copy. Whose items are:Besides, ETCs are duplicated. | |
Null | To remove just as removeType does. |
Key(s) | Type | Details | Default | |
---|---|---|---|---|
fromJson | Function | TPD value conversion from JSON. |
| angular.identity |
toJson | The same to JSON. | Caller of own toJSON method (if exists) | ||
input | String | HTML template. | If multi-level or multiple tags, you have to mark the main input element by tpd-target attribute. | Current definition of TPD type 'string' |
Object | DOM element | |||
Function |
| |||
Array | Collection of the mentioned types (string, function... or even, allowing unlimited nesting, another array!) that will be joined. | |||
output | Same as above | Use $tpdValue to manage the value. | '<span>{{$tpdValue}}</span>' |
Gets it.
Removes it and also in ETCs. Exceptionally, 'string'
is undeletable.
With name
as array of strings, it can be applied over more than one TPD type.
Sets a TPD component.
Param | Type | Details |
---|---|---|
selector | String | CSS selector. |
content | Same as option input , except for the following | TPD content. Functions can be used inside joining arrays, with selector's element (read-only) as argument. |
Function | To overwrite:
| |
Null | To remove just as removeComponent does. | |
ec (optional) | Object | ETCs. With keys as TPD type names while each value are formed by its TPD container with types like option input . |
Function | To overwrite:
|
When Typrod activates, collects the coincidences and priors the TPD component of most CSS specificity and oldest.
Gets it (array with content
and maybe ec
).
Removes it.
tpd
has two methods that return the corresponding read-only stored (all types transformed as possible to string) register: .types()
(as object) and .components()
(array).
Its direct execution (tpd()
) proportinates an object with both registers.
All of these should only be used in TPD contents and ETCs, except the first one (whose utilitation is free).
Put this attribute over the TPD component tag you want to locate the concerning TPD content. It contains an array where each object must to be formed as:
Key(s) | Type | Details |
---|---|---|
type (optional) |
String | Name of registered TPD type. Defaults to 'string' . |
name |
String | Name of param (where TPD value is saved) and a glue between its directive and this current one. |
label (optional) |
String | Caption text (HTML markup available) of tag with tpd-label . |
required (optional) |
Boolean | Input mandatority. |
min /max (optional) |
Any | Minimum/maximum of TPD value. |
And other custom ones are permitted for a not-generic using.
Also it is possible to reduce it putting an array (instead of the entire object) following this order: name
, label
, required
, type
and the rest (in an object).
So, ['isOk', 'OK?', false, 'boolean', { customKey1: 'one', customKey2: 'two' }]
equals to { type: 'boolean', name: 'isOk', label: 'OK?', required: false, customKey1: 'one', customKey2: 'two' }
.
Besides, accompanying this directive, in the same tag, tpd-values
is placed, determining the TPD JSON values (manipulated by fromJson
and toJson
). This pure attribute is optative but its exclusion has no much sense.
Ubicated as attribute solely on TPD containers, Typrod turns these into a repeatedly instantiated element by ng-repeat
and generates these scope variables:
TPD formatted values, opposite reflection of tpd-values
's.
Relative to each tpd-data
's item, it is formed by object of TPD property.
The correspondent TPD formatted value, of each item too.
If a serie of adjacent elements must to be repeated (instead of just one), substitute this directive with tpd-prop-start
and tpd-prop-end
as ng-repeat-start
and ng-repeat-end
do.
Labels the attributed element.
As tagnames, these ones are substituted by the extracted HTML of correspondent options of TPD types.
Typrod proportions some built-in registrations:
Name | Details | Extra tpd-data 's keys |
---|---|---|
'string' |
For single-line text. | |
'search' |
Text too but within <input type="search"> . |
|
'password' |
Outputs hiding characters. | |
'text' |
Multi-line. | To define the rows number, rows . |
'number' |
||
'range' |
Percentage. | |
'boolean' |
||
'date' |
||
'time' |
||
'datetime' |
||
'week' |
||
'month' |
||
'option' |
Single <select> . |
To fill its list, options with a string of scope's array (formed by objects with pairs id -label ). |
'options' |
The same but multiple. | |
'color' |
Hexadecimal color. | |
'url' |
URL. | |
'email' |
E-mail address. | |
'tel' |
Telephone number. |
You have namesake 'form'
. It rawly prints <div>
s with <label>
and input, and a submit button. You have to add the ng-submit
directive by yourself and data-name
attribute as namespace of labelable elements.
<dl>
s exposes labels in <dt>
s and outputs in <dd>
s.
'table'
: shows a labeled head and record rows. Place attributedata-tpd-values
with an array whose every item will be captured bytpd-values
s with scope variable$tpdRowValues
.'thead, tfoot'
: labels<th>
s.'tbody > tr'
: outputs<td>
s.