Developer forum

Forum » Swift » Partials with Models in an App Template file

Partials with Models in an App Template file

Joseph Vause
Reply

Hi,

Just wondered if this was possible.

I was just reading this: https://doc.dynamicweb.com/template-tags/introduction/other/includes-partial-views 

and wondered if there is a way that we can use Partials/Includes in a .cshtml file that allows model parameters and inherits from:

@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>

The guide insists that is must be a Page or Paragraph viewmodel that is inherited to allow @RenderPartial()

I am building a checkout flow (templates inside steps of the cart app), and on each page template we have several parts that ideally should be re-used as a partial and shared across all pages, but are not something we want to add into the visual editor of the cart app as they appear inside the main paragraph in various places, based on screen size.

Currently we have them rendered like this, but they differ only the variables that they need, such as a number and text 

@Include("Helpers/SummarySidebar.cshtml")

I'm aware you can have variables declared in the parent razor file and these are available to the rendered HTML that is rendered as part of the Include, however this is messy and doesn't really lend itself well to re-usability. It means that each Include must have its variables rendered in the @{} tag on the parent which can be unwieldy.

It also doesn't stop compilation errors when someone takes this and puts in on another page and neglects to set the same variables required for it in the parent file that they are working in.

I can see that @Include() has an override:

public override TemplateWriter Include(string name, object model, Type modelType)

However i am unsure how to use this as i get errors during compilation and also cannot see a way to easily access the object passed in here as a model in the Included template to allow me to get the values set back out.

Whn trying to use the above overload i this gives the error System.ArgumentException: Please either set a template manager to resolve templates or add the template 'Helpers/SummarySidebar.cshtml'!
 

If there is a way to do this, it would be very helpful to allow us to not have to have very similar templates with different names, or mean hard coding values into each one, which is also not ideal.

 

Kind regards, 

Joe


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Joe

Big topic!

There are 2 types of templates - tagbased and viewmodel based.

In viewmodel based templates, you can call @RenderPartial(template, model)

In tagbased templates, you do not have access to RenderPartial. But you can create something similar.

But first - you seem to be working with the cart. The cart it self is a module you can attach to a paragraph - and that cart module is still using the template tags. 
If you need to render cart related information in other templates, e.g. a paragraph or pageview template, both of which are viewmodel based templates, you can use the CartViewmodel that sits on the PageViewmodel. So in any viewmodel based template you can do this:

@{
 var cart = Dynamicweb.Frontend.PageView.Current().GetPageviewModel().Cart;
 <div>@RenderPartial("myCartSummary.cshtml", cart)</div>
}
And then have a template that looks like this
<!--myCartSummary.cshtml-->
@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.CartViewModel>
@using Dynamicweb.Frontend
<div>@Model.TotalProductsCount</div>

If you are not in a viewmodel based template, that is a tagbased template, you can do other fun stuff - below some rough boiler plate code for creating your own models and render them as partials:

You can create a cshtml file like this that will be used as include in all the places you want to render the same things - this file holds a functions section that defines custom viewmodels and also contains a custom version of renderpartial that you can then call in templates that are tagbased:

@functions{
 /*MyCustomModels.cshtml*/
 public class myCustomViewModel:ViewModelBase
    {
        public string? MyProperty { get; set; }
    }

 public class myOtherCustomViewModel : ViewModelBase
 {
 public int? MyOtherProperty { get; set; }
 }

 public string MyRenderPartial(string templatePath, ViewModelBase model)
 {
 var template = new Template(templatePath);
 template.SetViewModel(model);
 return template.Output();
 }
}
To consume the above, you include the above template, create an instance of a viewmodel and call renderpartial. You might not want to have the MyCustomModels also hold a function to create you instances of the custom viewmodels instead of doing it where you consume it.
@{/*AnyTemplate.cshtml*/}
@Include("MyCustomModels.cshtml")
@{
 var myModel = new myCustomViewModel() { MyProperty = "Hello World" };}
 <div>@MyRenderPartial("someSubfolder/myCustomViewModelTemplate.cshtml", myModel)</div>
}
 
You have  not specified if you are on DW10 or DW9 - there might be smaller differences in syntax, so beware if that.

 

You must be logged in to post in the forum