Page History
...
- A new component should consist of at least 3 files, in the same folder
- an HTML file, containing the template e.g.
sidebar.component.html
- an SCSS file, containing the style. Create this even if it's to remain empty. e.g.
sidebar.component.scss
- a TypeScript file, containing the component definition e.g.
sidebar.component.ts
- Its
templateUrl
attribute should contain a reference to the HTML file: e.g.templateUrl: './sidebar.component.html'
- Its
styleUrls
attribute (this is an array) should contain a reference to the style file: e.g.styleUrls: ['./sidebar.component.cssscss']
- Note that styleUrls refers to a CSS file rather than an SCSS file.That's because the AoT build process doesn't yet support SCSS, and the SCSS files get converted to CSS ahead of time. More information in the comments on this PR.
- Its
- it's selector attribute should start with ds- This ensures the component name contains a dash, and indicates it's a dspace component. e.g. selector: 'ds-sidebar'
Example:
Code Block language js @Component({ selector: 'ds-sidebar', styleUrls: ['./sidebar.component.cssscss'], templateUrl: './sidebar.component.html' }) export class SidebarComponent { }
- an HTML file, containing the template e.g.
...
- General
- Avoid writing (S)CSS if you can. Instead use Bootstrap 4 CSS classes and components where possible. That way it will be much easier to keep the style consistent across many different contributors.
- If you want to use a bootstrap component, take a look at the ng-bootstrap docs first. Chances are they've already turned it into an angular component for you.
- If you need to add margins, padding, change font-sizes or colors etc, make use of the bootstrap variables rather than entering numerical values. (e.g. write
margin-bottom: $spacer-y;
instead ofmargin-bottom: 15px;
andcolor
instead of: $brand-primary;
color: #0275d8;
- If there's no other way but to add a numerical value or color code yourself, consider turning it in to a variable, so it can be reused by others. Also calculations that are used more than once can benefit from being stored as variables: e.g.
$ds-table-margin-bottom: ($font-size-base * 2) - ($gutter-width / 2);
Component Styles
- Angular 2 makes use of component styles. By default, these can't leak out and affect the style of other components. Not even child components
- The style for a component should go in a file called
name.component.scss
, in the same directory as the component. e.g. forsrc/app/home/home.component.ts
the component style file issrc/app/home/home.component.scss
. - Note that the
styleUrls
parameter of the component refers to a CSS file, not an SCSS file. That's because the AoT build process doesn't yet support SCSS, and the SCSS files get converted to CSS ahead of time. More information in the comments on this PR.
i18n
- Don't hard code user-facing text in components. We're using ng2-translate for i18n. You use it by adding your key to resources/i18n/en.json, and then using that key in the component with the
translate
pipe. e.g.:- in en.json put:
"my-route.my-component.my-label-descriptor": "My User Facing Text";
- in your component put:
"<h1>{{ 'my-route.my-component.my-label-descriptor' | translate }}</h1>"
- in en.json put:
- For more info see the ng2-translate docs
...
- There is a DataService for each type of DSpaceObject.
- These data services ensure resources get fetched from the rest api (the mock rest api at this point), and stored in the ngrx store
- The find methods in the DataServices return an Observable stream of RemoteData objects
- RemoteData objects contain the status of the request (loading/failed/succeeded) and the data (or error message), as observables.
This gist shows how you would use it in practice:
In the component I specify that
collectionData
has the typeRemoteData<Collection[]>
specifycollection$
. The dollar is a convention to indicate an observableIn the OnInit:
this.collectionData collection$ = this.cds.findAll();
And then in the template, handle the different cases: dedicated messages for
isLoading
andhasFailed
and the actual data forhasSucceeded
of course in a more realistic scenario you might send the error to a notification service instead of handling it yourself
The In the template I use an
ng-container
and theasync
pipe allows you to use observables in the template as if they were plain objects.Because of the observables, the template will update automatically if the data in the store gets updatedto unwrap the observable: every time the observable changes the contents of this block will be re-rendered, andcollectionRD
will have the latest valueThe question marks check for null or undefined: the rest of the statement won't be executed unless that variable before the question mark has a value.