
Hello dear developer. I hope you are doing all right 🙂
Today’s post will be about how ChatGPT can be a good friend when you need to “convert” Razor views to NextJs.
The other day we wanted to do a POC for a table component in NextJs.
*We did not want to use the “Richtext approach” for various reasons.
So we started googling, why re-invent the wheel 😉
And we found a great piece/post from Adam Seabridge – CREATING A TABLE COMPONENT FOR SITECORE
Exactly what we needed! But there was one caveat, it was for ASP.Net MVC. Meaning we will have to convert the razor view somehow.
ChatGPT to the rescue!
*For lazy Sitecore dinosaurs 😉
So basically, I asked my dear “rubber duck”( ChatGPT ):
Dear ChatGPT, I have the following Razor view code:
@inherits MyWebsite.Models.ITable
@{
var tableRowsToSkip = 0;
if (DataSource.HasHeaderRow)
{
tableRowsToSkip = 1;
}
var tableRowsToRemove = 1;
if (DataSource.HasFooterRow && DataSource.HasHeaderRow)
{
tableRowsToRemove = 2;
}
else if (DataSource.HasFooterRow)
{
tableRowsToRemove = 1;
}
else
{
tableRowsToRemove = 0;
}
}
<!--start table -->
<div class="table">
<table class="table__table">
@if (this.DataSource != null)
{
if (this.DataSource.TableRows != null && this.DataSource.TableRows.Any())
{
if (DataSource.HasHeaderRow)
{
<thead>
<tr>
@foreach (var headerCell in DataSource.TableRows.ToList().First().TableCells)
{
<th>@Editable(headerCell, x => x.Text)</th>
}
</tr>
</thead>
}
<tbody>
@foreach (var tableRow in this.DataSource.TableRows.Skip(tableRowsToSkip).Take(DataSource.TableRows.Count()-tableRowsToRemove))
{
<tr>
@foreach (var tableCell in tableRow.TableCells)
{
<td>@Editable(tableCell, x => x.Text)</td>
}
</tr>
}
</tbody>
if (DataSource.HasFooterRow)
{
<tfoot>
<tr>
@foreach (var footerCell in DataSource.TableRows.ToList().Last().TableCells)
{
<td>@Editable(footerCell, x => x.Text)</td>
}
</tr>
</tfoot>
}
}
else if (Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
<div class="message">
<h2>No Table Rows</h2>
<p>No Table Rows have been created for this Table. </p>
</div>
}
}
else if (Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
<div class="message">
<h2>No datasource Set</h2>
<p>Please select a datasource for this Table.</p>
</div>
}
</table>
</div>
<!--end table -->
Hello! This Razor view code appears to be used to generate a table view in a web application. Let me break it down for you:
- The first line “@inherits MyWebsite.Models.ITable” means that this view is based on the ITable model defined in the MyWebsite.Models namespace.
- The code block that follows sets two variables: tableRowsToSkip and tableRowsToRemove. These variables are used later to control which rows are displayed in the table, based on whether the data source has header and footer rows.
- The next section of code checks whether the DataSource property is not null, and whether the TableRows property is not null and contains any elements.
- If the above conditions are met, the view starts building the table structure by first checking if there is a header row. If there is a header row, the view renders the header row with a “th” cell for each table cell in the header row.
- Next, the view renders the body of the table. It does this by iterating through each table row in the DataSource.TableRows collection, skipping the number of rows specified by the tableRowsToSkip variable and removing the number of rows specified by the tableRowsToRemove variable. For each table cell in each table row, the view renders a “td” cell with the text of the cell.
- If there is a footer row, the view renders the footer row with a “td” cell for each table cell in the footer row.
- If the DataSource.TableRows collection is empty and the page is being viewed in Experience Editor mode, the view displays a message indicating that no table rows have been created.
- If the DataSource property is null and the page is being viewed in Experience Editor mode, the view displays a message indicating that no data source has been set.
Overall, this Razor view code generates a table view that is responsive to the presence of header and footer rows in the data source, and provides helpful messages to the user if the data source is empty or missing.
Wow! What a breakdown! No need for documentation anymore, just let ChatGPT do it for you 🙂
Ok, let’s continue…
I would like to convert this code to nextjs, can you please try?
Sure! Here’s an example of how you can convert the code to Next.js:
import React from 'react';
const MyTable = ({ dataSource }) => {
let tableRowsToSkip = 0;
if (dataSource.hasHeaderRow) {
tableRowsToSkip = 1;
}
let tableRowsToRemove = 1;
if (dataSource.hasFooterRow && dataSource.hasHeaderRow) {
tableRowsToRemove = 2;
} else if (dataSource.hasFooterRow) {
tableRowsToRemove = 1;
} else {
tableRowsToRemove = 0;
}
return (
<div className="table">
<table className="table__table">
{dataSource && dataSource.tableRows && dataSource.tableRows.length > 0 ? (
<>
{dataSource.hasHeaderRow && (
<thead>
<tr>
{dataSource.tableRows[0].tableCells.map((headerCell, index) => (
<th key={index}>{headerCell.text}</th>
))}
</tr>
</thead>
)}
<tbody>
{dataSource.tableRows.slice(tableRowsToSkip, dataSource.tableRows.length - tableRowsToRemove).map((tableRow, rowIndex) => (
<tr key={rowIndex}>
{tableRow.tableCells.map((tableCell, cellIndex) => (
<td key={cellIndex}>{tableCell.text}</td>
))}
</tr>
))}
</tbody>
{dataSource.hasFooterRow && (
<tfoot>
<tr>
{dataSource.tableRows[dataSource.tableRows.length - 1].tableCells.map((footerCell, index) => (
<td key={index}>{footerCell.text}</td>
))}
</tr>
</tfoot>
)}
</>
) : (
<div className="message">
<h2>{dataSource ? 'No Table Rows' : 'No datasource Set'}</h2>
<p>{dataSource ? 'No Table Rows have been created for this Table.' : 'Please select a datasource for this Table.'}</p>
</div>
)}
</table>
</div>
);
};
export default MyTable;
And bam! This is not perfect, but it is a great start. So after some “tweaking” in the nextjs code, we got the final result:
import {
Text,
Field,
useSitecoreContext,
withDatasourceCheck,
} from '@sitecore-jss/sitecore-jss-nextjs';
import { ComponentProps } from 'lib/component-props';
type TableProps = ComponentProps & {
fields: {
items: [];
TableHasHeaderRow: Field<boolean>;
TableHasFooterRow: Field<boolean>;
};
};
type TableCellProps = ComponentProps & {
TableCellValue: Field<string>;
};
export const Table = (props: TableProps): JSX.Element => {
const { fields } = props;
const tableRowItems = fields?.items || [];
const { sitecoreContext } = useSitecoreContext();
const isEditing = sitecoreContext && sitecoreContext.pageEditing;
const hasHeader = fields.TableHasHeaderRow.value || true;
const hasFooter = fields.TableHasFooterRow.value || false;
let tableRowsToSkip = 0;
if (hasHeader) {
tableRowsToSkip = 1;
}
let tableRowsToRemove = 1;
if (hasFooter && hasHeader) {
tableRowsToRemove = 2;
} else if (hasFooter) {
tableRowsToRemove = 1;
} else {
tableRowsToRemove = 0;
}
return (
<div className="table">
<table className="table__table">
{props.fields && tableRowItems && tableRowItems.length > 0 ? (
<>
{hasHeader && (
<thead>
<tr>
{tableRowItems[0].fields.items.map(
(
headerCell: {
fields: TableCellProps;
},
index: React.Key | number
) => (
<th key={index}>
<Text field={headerCell.fields.TableCellValue} />
</th>
)
)}
</tr>
</thead>
)}
<tbody>
{tableRowItems
.slice(tableRowsToSkip, tableRowItems.length + 1 - tableRowsToRemove)
.map(
(
tableRow: { fields: { items: { fields: TableCellProps }[] } },
rowIndex: React.Key
) => (
<tr key={rowIndex}>
{tableRow.fields.items.map(
(
tableCell: {
fields: TableCellProps;
},
cellIndex: React.Key
) => (
<td key={cellIndex}>
<Text field={tableCell.fields.TableCellValue} />
</td>
)
)}
</tr>
)
)}
</tbody>
{hasFooter && (
<tfoot>
<tr>
{tableRowItems[tableRowItems.length - 1].fields.items.map(
(
footerCell: {
fields: TableCellProps;
},
index: React.Key
) => (
<td key={index}>
<Text field={footerCell.fields.TableCellValue} />
</td>
)
)}
</tr>
</tfoot>
)}
</>
) : (
isEditing && (
<div className="message">
<h2>{props.fields ? 'No Table Rows' : 'No datasource Set'}</h2>
<p>
{props.fields
? 'No Table Rows have been created for this Table.'
: 'Please select a datasource for this Table.'}
</p>
</div>
)
)}
</table>
</div>
);
};
export default withDatasourceCheck()<TableProps>(Table);
I can’t wait to play around with ChatGPT 4
That’s all for now folks 😊
This is incredible! We’ve talked many times about the transition from Razor to JSS and this will speed things up! Thanks!
LikeLiked by 1 person
Im glad it helped you guys 😄
LikeLike