29
loading...
This website collects cookies to deliver better user experience
// GET: Movies
public async Task<IActionResult> Index() { ... }
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id) { ... }
// GET: Movies/Create
public IActionResult Create() { ... }
// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(MovieEditorViewModel model) { ... }
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id) { ... }
// POST: Movies/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, MovieEditorViewModel model) { ... }
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id) { ... }
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id) { ... }
<script src="https://unpkg.com/[email protected]"></script>
in my "/Views/Shared/_Layout.cshtml" file:...
<div class="container">
© 2021 - MvcHtmx - @DateTime.Now.ToLongTimeString()
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="https://unpkg.com/[email protected]"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
<a asp-action="Create">Créer</a>
in the table header to allow you to create a new movie.<a href="/movies/create/">Créer</a>
. When the user clicks on this link, the browser hits the web server via an HTTP GET request and ASP.NET Core performs the "Create" action from the "MoviesController" controller which returns a new page to the browser.@RenderBody()
. And from an HTML perspective, the change is in the content of the <main>
tag.</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<main>
tag. hx-get="/movies/create/"
to indicate to HTMX that it will have to make an HTTP GET request on the URL "/movies/create/", which corresponds to the "Create" action of the "MoviesController" controller.hx-target="main"
to target where HTMX will have to insert the content returned by the action (instead of the current content of the tag <main>
).hx-push-url="true"
so that the browser address bar is updated.<td>
<a asp-action="Create" hx-target="main" hx-push-url="true" hx-get="/movies/create/">Créer</a>
</td>
<td>
<a href="/movies/create/" hx-target="main" hx-push-url="true" hx-get="/movies/create/">Créer</a>
</td>
<a href="/movies/create/" hx-target="main" hx-push-url="true">Créer</a>
in order to avoid "href" and "hx-get" attributes being duplicated.<td>
<a asp-action="Edit" asp-route-id="@item.Movie_ID"
hx-target="main" hx-push-url="true" hx-get="/movies/edit/@item.Movie_ID/">Modifier</a> |
<a asp-action="Details" asp-route-id="@item.Movie_ID"
hx-target="main" hx-push-url="true" hx-get="/movies/details/@item.Movie_ID/">Consulter</a> |
<a asp-action="Delete" asp-route-id="@item.Movie_ID"
hx-target="main" hx-push-url="true" hx-get="/movies/delete/@item.Movie_ID/">Supprimer</a>
</td>
<a href="/movies/">Annuler</a>
to exit the page and return to the movie list. This link is generated via the following TagHelper:<a asp-action="Index">Annuler</a>
<a asp-action="Index" hx-target="main" hx-push-url="true" hx-get="/movies/">Annuler</a>
<a asp-action="Edit" asp-route-id="@Model.Movie_ID" class="btn btn-secondary"
hx-target="main" hx-push-url="true" hx-get="/movies/edit/@Model.Movie_ID/">Modifier</a>
<form asp-action="Create" method="post" class="form-horizontal">
...
</form>
asp-action="Create"
because I make sure to always post a form on the same URL that displays this form. This is much better if there are any input errors detected afterwards on the server side.<form method="post" class="form-horizontal">
...
</form>
<form method="post" class="form-horizontal" hx-post="/movies/create/">
...
</form>
<form>
tag.<form method="post" class="form-horizontal" hx-post="/movies/edit/@Model.Movie_ID/">
...
</form>
<form method="post" class="form-horizontal" hx-post="/movies/delete/@Model.Movie_ID/">
...
</form>
return View(data)
. The ASP.NET Core view system then combines the data from this model, the Razor code from the view and the Razor code from the layout to generate a full HTML page that it sends back to the browser.return View(data)
, we can also use return PartialView(data)
and in this case the layout is not included.if (Request.Headers.ContainsKey("HX-Request"))
{
// When we respond to HTMX
return PartialView(model);
}
return View(model); // If we did not use HTMX
private IActionResult HtmxView(object model)
{
if (Request.Headers.ContainsKey("HX-Request"))
{
Response.Headers.Add("HX-Push", Request.Path.ToString());
return PartialView(model);
}
return View(model);
}
hx-push-url="true"
I have previously added to <a>
links. Thus I can delete them without losing functionalities.<script src="https://unpkg.com/[email protected]"></script>
in the layout.<a asp-action="Toto">Tutu</a>
with <a asp-action="Toto" hx-target="main" hx-get="/movies/toto/">Tutu</a>
hx-target="main" hx-get="/movies/toto/@Un_ID/"
to links <a asp-action="Toto" asp-route-id="@Un_ID">Tutu</a>
<form method="post" ...
with <form method="post" hx-post="/movies/toto/xxx" ...
return View(model);
with return HtmxView(model);
private IActionResult HtmxView(object model) { ... }
to the controller<a-htmx>
and <form-htmx>
so that all these modifications are less complicated (and to avoid duplicates between "href" and "hx-get").<a asp-action="Toto">Tutu</a>
to <a-htmx asp-action="Toto">Tutu</a-htmx>
!