Note, I'm the author of Angular-Slickgrid
You shouldn't add an href link in a Formatter, it's not safe (XSS injection, like <script>
tag) and it shouldn't be trusted, also you don't want to use a plain href since that will reload the entire page (outside of the SPA)... What you should do instead is use the click
event and when that particular column is clicked then do something. That is exactly what I've done in our project, my Formatter makes it look like a link but in reality the user can click anywhere in the cell (most user will never notice that, especially so if your column width is the size of the text) and from an event handler you can do an Angular route change while staying in the SPA (Single Page App).
So like I said, I have a Custom Formatter to make it look like an hyperlink and here is the code (with translation in our case)
import { Formatter, Column } from 'angular-slickgrid';
export const openFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: any) => {
const gridOptions = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {};
const translate = gridOptions.i18n;
let output = '';
if (translate && translate.instant) {
const openTxt = translate.instant('OPEN');
const openForDetailTxt = translate.instant('OPEN_FOR_DETAILS');
output = `<span class="fake-hyperlink" title="${openForDetailTxt}">${openTxt}</span>`;
}
return output;
};
For the fake hyperlink, I have this simple SASS styling
.fake-hyperlink {
cursor: pointer;
color: blue;
&:hover {
text-decoration: underline;
}
}
in the View I watch a cell click
event via the (sgOnClick)
<angular-slickgrid
gridId="userGrid"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
(onAngularGridCreated)="angularGridReady($event)"
(sgOnClick)="handleOnCellClick($event.detail.eventData, $event.detail.args)">
</angular-slickgrid>
and in the Component, for the cell click handler I do a switch case on the column name and when I know the user clicked on that column I then do my action (in the example below, it's the column field userNumber
), from the args
you can get the grid
and get most of what you want with regular SlickGrid methods.
handleOnCellClick(event, args) {
const grid = args.grid;
const selectedUser = grid && grid.getDataItem(args.row) as User;
const columnDef = grid && grid.getColumns()[args.cell];
const field = columnDef && columnDef.field || '';
switch (field) {
case 'userNumber':
const url = `/users/${selectedUser.id}`;
// we can also look at the Event used to handle Ctrl+Click and/or Shift+Click
if (event.ctrlKey || event.shiftKey) {
const openUrl = this.location.prepareExternalUrl(url);
window.open(openUrl, '_blank'); // open url in a new Browser Tab
} else {
this.router.navigateByUrl(url); // or open url in same Tab
}
break;
default:
// clicked on any other column, do something else?
// for example in our project we open a sidebar detail view using Bootstrap columns
// this.openSidebar();
break;
}
}
On a final note and to give you a more detailed description of our project, if the user clicks on the column which has the fake link it will then execute the click handler pass through the switch case and will route to the particular user detail page, if however the user clicks anywhere else it will open a sidebar (we use Bootstrap Columns. For a quick explanation of how I do a sidebar, I simply change the grid container with Bootsrap classes from col-sm-12
to col-sm-8
and the sidebar to col-sm-4
and then call a grid resize (and vice-versa when I close it). Our sidebar is like a quick view (a condensed detail page) on the other end if they click on the fake hyperlink column it will open the full user detail page.
You can also reuse this concept with a Context Menu, Grid Menu, etc...
Give it a try... and a Star upvote if you like the lib ;)