Template object field enforcement - templates

Go provides great build in HTML templating functionality, however for me it is important that I can ensure certain fields will always be available to templates in my application. A good example of this is a title field, which needs to be shown on every HTML page.
Given the following pages:
Home
Register
Contact
I would likely create the following objects for the templating system:
HomePage struct
RegisterPage struct
ContactPage struct
Is there a recommended way to ensure that the structs for each page have certain fields available to them?
Ideally I would implement this through Polymorphism, but that isn't officially supported in Go. The alternative, embedding doesn't appear to have any enforcement, i.e all of the child structs can embed a parent struct but don't have to.
Let me know if I haven't expressed my question clearly enough.

Executing a template does not enforce anything to the parameters, Template.Execute() accepts a value of type interface{}.
You are the one creating the HomePage, RegisterPage and ContactPage structs. What stops you from embedding a BasePage struct with the required fields? Are you worried you will forget about it? You will notice it at the first testing, I wouldn't worry about that:
type BasePage struct {
Title string
Other string
// other required fields...
}
type HomePage struct {
BasePage
// other home page fields...
}
type RegisterPage struct {
BasePage
// other register page fields...
}
If you want from code to check if page structs embed the BasePage, I recommend another way: interfaces.
type HasBasePage interface {
GetBasePage() BasePage
}
Example HomePage that implements it:
type HomePage struct {
BasePage
// other home page fields...
}
func (h *HomePage) GetBasePage() BasePage {
return h.BasePage
}
Now obviously only pages that have a GetBasePage() method can be passed as a value of HasBasePage:
var page HasBasePage = &HomePage{} // Valid, HomePage implements HasBasePage
If you don't want to use interfaces, you can use the reflect package to check if a value is a struct value and if it embeds another interface. Embedded structs appear and can be accessed like ordinary fields e.g. with Value.FieldByName(), with the type name being the field name.
Example code using reflect to check if a value embeds BasePage:
page := &HomePage{BasePage: BasePage{Title: "Home page"}}
v := reflect.ValueOf(page)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
fmt.Println("Error: not struct!")
return
}
bptype := reflect.TypeOf(BasePage{})
bp := v.FieldByName(bptype.Name()) // "BasePage"
if !bp.IsValid() || bp.Type() != bptype {
fmt.Println("Error: struct does not embed BasePage!")
return
}
fmt.Printf("%+v", bp)
Output (try it on the Go Playground):
{Title:Home page Other:}

Related

How to update nested state in Ember Octane

So my situation is as follows:
I got a component with a couple of input fields that represent a contact and are filled with data from a service:
#service('contact-data') contact;
Each field stands for one property that is accessed via
{{contact.properties.foo}}
I have the properties saved as a JS object to easily filter out empty fields when using them and I tracked it with #tracked like so:
export default class MyService extends Service {
#tracked properties = {id: 0, foo: "", bar : "abc", };
#action updateProperty(name, value) {
this.properties[name] = value;
}
}
However, the properties do not re-render properly in the component and the textfields do not get updated.
I'd appreciate any help with this! Thanks!
Any time you have a bunch of nested state like that which needs to be tracked, just tracking the top-level object won't cause updates to the internals of that object to propagate out. You need to track the internal properties, or you need to reset the whole object you're tracking.
You have basically two rough options for dealing with updates to those internal properties:
If the object has a well-known shape, extract it into a utility class which uses #tracked on the fields, and instantiate the utility class when you create the service. Then updates to those fields will update.
If the object is really being used like a hash map, then you have two variant options:
Use https://github.com/pzuraq/tracked-built-ins, if you don't need IE11 support
Do a "pure functional update", where you do something like this.properties = { ...this.properties, foo: newValue };
Of these, (1) is pretty much always going to be the cheapest and have the best performance. Doing (2.1) will be a little more expensive, because it requires the use of a Proxy, but not enough that you would normally notice. Doing (2.2) will end up triggering a re-render for every property in the properties used anywhere in the app, even if it didn't change.
In the case you've described, it appears the fields are well known, which means you should reach for that class. The solution might look something like this:
import Service from '#ember/service';
import { action } from '#ember/object';
import { tracked } from '#glimmer/tracking';
class TheProperties {
#tracked id;
#tracked foo;
#tracked bar;
}
export default class MyService extends Service {
properties = new TheProperties();
#action updateProperty(name, value) {
this.properties[name] = value;
}
}
Note that #tracked installs getters and setters in place of plain class properties, so if you need to use this for a JSON payload somewhere or similar, you'll also want to implement toJSON on the utility class:
class TheProperties {
#tracked id;
#tracked foo;
#tracked bar;
toJSON() {
let { id, foo, bar } = this;
return { id, foo, bar };
}
}
There's another add-on that does basically the same thing for Array and Objects as tracked-built-ins.
It's a proxy that basically notifies the root that an update has occurred somewhere. The advantage against tracked-built-ins is that the nesting depth is not limited as it's common for JSON to have deep nesting.
The drawbacks are similar to tracked-built-ins in terms of performance. Use it sparingly and try not to use it in tables with hundreds/thousands of rows as re-rendering is going to be not performant.

golang template.Execute and struct embedding

I have a little website project written go where you can store links, and I ran into a problem :
The website has many different pages which show different information so you need to pass template.Execute a different kind of a struct. But every page also needs info like username and tags, which are displayed in sidebar. I tried to make something like this instead of just making completely new struct type for each page.
http://play.golang.org/p/VNfD6i8p_N
type Page interface {
Name() string
}
type GeneralPage struct {
PageName string
}
func (s GeneralPage) Name() string {
return s.PageName
}
type PageRoot struct {
Page
Tags []string
IsLoggedIn bool
Username string
}
type ListPage struct {
Page
Links []Link
IsTagPage bool
Tag string
}
type GalleryPage struct {
Page
Image Link
Next int
Previous int
}
But I get an error when I execute the template: "fp.tmpl" at <.Links>: can't evaluate field Links in type main.Page
The part of the template where the error occurs:
{{with .Page}}
{{range .Links}}
<tr>
<td>{{if .IsImage}}<img src="{{.Url}}" />{{end}}</td>
<td>{{.Name}}</td>
<td>{{.Url}}</td>
<td>{{.TagsString}}</td>
</tr>
{{end}}
{{end}}
And {{.Name}} doesn't work. (It's the function embedded from GeneralPage)
You're embeding the Page interface, but what you need is GeneralPage.
Maybe you can use a map[string]interface{} to store your data (and then check if not-nil in your template), it easier.
But you can share the main layout and just change the detail (like a master page).
Look at http://golang.org/pkg/text/template/#example_Template_share

Reusable Scala code for all views in Play

I know I can declare a reusable pure Scala block like this in a template:
#title(text: String) = #{
text.split(' ').map(_.capitalize).mkString(" ")
}
I can now call #title("someString") in the template but this code block is not accessible from outside this template.
How can I declare such a block that is accessible from other templates as well?
I've tried to create a new template title.scala.html like this:
#(text : String)
#{
text.split(' ').map(_.capitalize).mkString(" ")
}
I can now call #title("someString") from any template I want, but this doesn't give me the exact same result as the first block, inside the template (I assume in the first case it returns a String whereas it returns Html in the second case).
I'm using Play framework 2.0.4 and I'm coding in Java (hence my limited Scala knowledge).
Using tags is targeted for building reusable blocks of HTML code, therefore it returns Html
To work easily with common types of data you can easily add a custom Java class (for an example in freshly created utils package (in app directory), and prepare in it all required formatters as a static methods:
utils.MyFormats.java:
package utils;
import org.apache.commons.lang3.text.WordUtils;
public class MyFormats {
public static String capitalize(String str) {
return WordUtils.capitalize(str);
}
public static int sumElements(int a, int b) {
return a + b;
}
}
In template:
<h2>Capitalized each word: #(utils.MyFormats.capitalize("foo bar"))</h2>
<h3>Sum of two integers, 2+3 = #(utils.MyFormats.sumElements(2, 3))</h3>

Looping over an array of objects in a template (Go)

I'm passing a struct (one element is an array of Category objects) to the template for rendering. In the template, I have code that looks something like this:
{.repeated section Categories}
<p>{#}</p>
{.end}
However, each Category has a few of its own elements that I need to be able to access (Title for instance). I have tried things like {#.Title} but I can't seem to find the proper syntax for accomplishing this. How do I access members of data in an array during a loop in a template?
You can just write {Title}.
Whenever the template package encounters an identifier, it tries to look it up in the current object and if it doesn't find anything it tries the parent (up to the root). The # is just there if you wan't to access the current object as a whole and not one of its attributes.
Since I'm not used to the template package either, I've created a small example:
type Category struct {
Title string
Count int
}
func main() {
tmpl, _ := template.Parse(`
{.repeated section Categories}
<p>{Title} ({Count})</p>
{.end}
`, nil)
categories := []Category{
Category{"Foo", 3},
Category{"Bar", 5},
}
tmpl.Execute(os.Stdout, map[string]interface{} {
"Categories": categories,
})
}

MVC - open page in View mode

Hi
I am trying to see if anybody has a briliant idea on how to implement View mode concept in MVC. So if the user opens a page, the page should open in view mode (all controls disabled), if they dont have edit priviledges else should open as normal. Please note that the View page has partial pages as well
I think you have total control on your page under MVC framework. If you are using standard MVC method to generate input controls, you could do following ways.
#Html.TextBox("MyTextBoxID", Model==null?"":Model.MyFieldValue, new {disabled = "disabled})
If you are not using standard MVC method to generate input controls. You can create your own method to generate input controls. For example in MyExt.cs
public static class MyExt
{
public static MvcHtmlString MyTextBox(this HtmlHelper html, string id, object value)
{
// check user privilege
if (CurrentUser.CanEditThisPage /*Implement your own logic here */)
return html.TextBox(id, value);
else
return html.TextBox(id, value, new {disabled = "disabled"});
}
}
And in your page
#using MyNamespace
...
#Html.MyTextBox("MyTextBoxID", Mode==null?"":Model.MyFieldValue)
Another Way
Pass an indicator from server side to client side and using javascript or JQuery to disable all controls.
#Html.Hidden("CanEdit", CurrentUser.CanEditThisPage)
In javascript
void pageLoad() {
if ($("#CanEdit").val() == "true"))
$("input").attr("disabled", "disabled");
}
Something like that (not sure about correctness of syntax :P)