Pass data correctly to another dust template - html

There is a base.tl which contains two columns like below:
<li class="column region">
{#partial placeholder = "region" id="column-region" }
{> "templates/partials/column" /}
{/partial}
</li>
<li class="column industry">
{#partial placeholder = "industry" id="column-industry" }
{> "templates/partials/column" /}
{/partial}
</li>
This is the column.tl which contains a input box. I want one of them is readonly and the other is not. So I add readOnly like this.
But I do not know how to parse the boolean readOnly from the base.tl to here.
<div class="column-content">
<input placeholder="{placeholder}"
class="add-preference-input"
type="text" {?readOnly}readonly{/readOnly} />
</div>
Seems like I parse the param like placeholder but it cannot tell it is a boolean. How do I parse a boolean to the partial template and let it be recognized? Is it possible or I have to use javescript to help it.

You're correct that Dust cannot pass booleans directly as params-- they'll just be stringified.
However, the {?exists} tag checks for existence, not truthiness. So you have several options.
Instead of passing true and false, pass "true" and "" (empty string)
{#partial placeholder="region" readonly="" id="column-region"}
Use the {#eq} helper from dustjs-helpers
{#eq key="readonly" value="true" type="boolean"}readonly{/eq}
Put variables in your context that are equal to true and false
{#partial placeholder="region" readonly=FalseContextVar}

Related

TypeError: "setting getter-only property "value"

Im trying update the input value but it returns this error:
TypeError: "setting getter-only property "value"
I created a function in angular for try modify the value:
modifyValue(searchCenter, centerId){
searchCenter.value = centerId._id;
}
centerId is the value that i want to asignate to input value.
And this is the html:
<p>
<label>Search a center</label>
<input type="text" name="searchCenter" class="form-control" #searchCenter='ngModel' [(ngModel)]="term" [(ngModel)]="user.center" required/>
</p>
<div class="center panel panel-default" *ngFor="let center of centers | filter:term">
<div class="panel-body">
<button (click)="modifyValue(searchCenter, center)" type="button" class="centers-button">{{center.name}}, {{center.community}},
{{center.municipality}}</button>
</div
>
Issue
You are trying to set the value property of string object which is wrong. string doesn't have any property called value.
Fix
You might be trying to set the value of term. You have two option to do so -
First change
Change in html
#searchCenter='ngModel'
to
#searchCenter
2.Second option is change in the ts file
modifyValue(searchCenter, centerId){
this.term = centerId._id;
}

Thymeleaf and Springboot project - tag names

I have a Springboot & Thymeleaf project that is generating the same "names" on my person inputs.
The controller looks like:
#GetMapping("/newEpisode")
public String episodeForm(Model model) {
model.addAttribute("episode", new Episode());
List<Country> countries = countryRepository.findAll();
Set<String> roles = new HashSet<>();
roles.add("Admin");
model.addAttribute("primaryPerson1",new EpisodePerson());
model.addAttribute("primaryPerson2",new EpisodePerson());
model.addAttribute("roles", roles);
model.addAttribute("countries", countries);
return "episode";
}
Some of my HTML looks like:
<input type="text" class="form-control person surname" style="text-transform: uppercase" data-property="surname" placeholder="SURNAME" th:field="${primaryPerson1.person.surname}"/>
But the generated name in the HTML for this tag is not unique:
<input type="text" class="form-control person surname" style="text-transform: uppercase" data-property="surname" id="surname1" placeholder="SURNAME" name="person.surname" value="">
Why are all the person tags in the html sharing the same name for example I have two :
name="person.surname"
You've misused the th:field attribute.
Its aim is to bind your input with a property in the form-backing bean. So you should either create separate forms for each object and use it in following manner:
<!-- Irrelevant attributes omitted -->
<form th:object="${primaryPerson1}">
<input th:field="*{person.surname}"/>
</form>
...or create a form-backing bean, which would combine both of your objects, e.g.:
public class EpisodeFormBean {
private List<EpisodePerson> episodePersons;
//getter and setter omitted
}
...then add it to a model in your episodeForm method...
EpisodeFormBean episodeFormBean = new EpisodeFormBean();
episodeFormBean.setEpisodePersons(Arrays.asList(new EpisodePerson(), new EpisodePerson()));
model.addAttribute("episodeFormBean", episodeFormBean);
...and use it in your template as follow:
<!-- Irrelevant attributes omitted -->
<form th:object="${episodeFormBean}">
<input th:field="*{episodePersons[0].person.surname}"/>
<input th:field="*{episodePersons[1].person.surname}"/>
</form>
In the second solution generated names would be unique. I think it's more suitable for your needs.
You should check out Tutorial: Thymeleaf + Spring as there it is well explained. Especially you should notice a phrase:
Values for th:field attributes must be selection expressions (*{...}),
which makes sense given the fact that they will be evaluated on the
form-backing bean and not on the context variables (or model
attributes in Spring MVC jargon).

angular 2 validation on dynamic generated fields in loop

I have a list of input fields that are generated with a model. I am trying to add validation to them.
The requirement is they should not be empty or less than 2 characters.
problem is in the documentation only shows validation with non-dynamically generated variable Name. My fields are all generated dynamically. So there is no tempVariableName I can hardcode (otherwise they conflict), so I created temp variable from the name of the property I binded the field to. So I came up with something like this :
<div *ngFor="let field of connector.configFields">
<label>{{field.name}}</label>
<input [(ngModel)]="field.value" [type]="field.name === 'Password' ? 'password' : 'text'"
placeholder="{{field.name}} (required)"
ngControl="[fieldName+field.name]"
required minlength="2"
#fieldName+[field.name]="ngModel" />
<div *ngIf="(fieldName+[field.name]).errors && ((fieldName+[field.name]).dirty || (fieldName+[field.name]).touched)">
<span *ngIf="(fieldName+[field.name]).errors.required">Enter Name</span>
<span *ngIf="(fieldName+[field.name]).errors.minlength">Name minimum at 2 characters</span>
</div>
</div>
and the configFields in typescript look like this :
export class FieldModel {
public name: string;
public type: string;
public value: any;
}
But this simply would not work. I am new to angular 2 so I am not exactly sure what I did wrong.
You can use the unique index for each field in the array. Use this together with the name attribute (and ngModel) which will evaluate each form controls separately. So each input field gets the unique name, eg:
name="f{{i}}"
where we get {{i}} from the iteration:
<div *ngFor="let field of connector.configFields; let i = index">
So finally, your template could look like this:
<form #myForm="ngForm">
<div *ngFor="let field of connector.configFields; let i = index">
<input name="f{{i}}" [(ngModel)]="field.value" [type]="field.name === 'Password' ? 'password' : 'text'" required #f="ngModel" minlength="2"/>
<div *ngIf="f.errors && (f.dirty || f.touched)">
<div *ngIf="f.errors.required"> This field is required </div>
<div *ngIf="f.errors.minlength"> Min 2 chars </div>
</div>
</div>
</form>
Here's a live
Demo
Prepare data in model and return to angular. Angular and hard logic in the template = bad friends.
But if you have a select option and if has *ngFor for option then error message loses its mapping, due second *ngFor loop
better to define custom class for error message and use css display: none or **block*
.custom-valid-box{
display: none;
}
.form-control-danger + .custom-valid-box{
display: block;
}

Play Framework 1.2.7 mysterious error with form

So I have a form with a submit button and a hidden field. The hidden field holds the value which will be used to query. When the user presses the submit button, the value is supposed to pass to the controller and the controller is supposed to query and then render a new page with the query result. Here is the code,
#{list items:courses, as:'course'}
<li>
${course.CourseCode}
#{form #Courses.detail()}
<div>
<input type="text" name="Code" value = ${course.CourseCode} />
</div>
<div>
<input type="submit" value="Course Detail" />
</div>
#{/form}
</li>
<br />
#{/list}
I was having problems with "Course" not found so I changed the hidden field to text. This is where the weird thing starts. I see only half the value of ${course.CourseCode}. For example, if course code = ICCS 101, I see "ICCS 101" in the list but in the text field I see only ICCS. I have no idea why this is happening.
Here is my controller
public static void detail(String Code){
System.out.println(Code);
List<Course> courses = Course.find("byCourseCode", Code).fetch();
int index = courses.size()-1;
if(index>=0){
Course course = courses.get(index) ;
render(course);
}
else{
notfound();
}
}
Edit::It seems like it truncates everything after the first white space.
In your view the value property of your input tag should be between quotes "..." otherwise everything after the first space will get truncated
<input type="text" name="Code" value="${course.CourseCode}" />

How to Get Model Data from Partial View?

I am creating a site in which I utilize partial views to display various bits of data about a single Model. Here is a bit of the HTML. (Note, all of these are contained within a single form and the Index page that these partials are rendered in is strongly typed to the main model. The main model contains various lists of data.)
<div id="tab1"><% Html.RenderPartial("Tab1", Model); %></div>
<div id="tab2"><% Html.RenderPartial("Tab2", Model.AnItemList1.FirstOrDefault<AnItemList1>()); %></div>
<div id="tab3"><% Html.RenderPartial("Tab3", Model.AnItemList2.FirstOrDefault()); %></div>
Here is ONE of the partial views headers (for 'tab2'):
<%# Language="C#" Inherits="System.Web.Mvc.ViewUserControl<AnItem1>" %>
The pages display correctly. The issue is that, when I enter data into the various parts of the partial pages and then submit the entire form (via POST), the data is not making it back to my data store (MSSQL) - but this only happens for any of the list items (that are contained within the Model). The first partial page does properly have its data set within the data store.
What am I doing wrong here? Should I only be passing the model to Html.RenderPartial and then get the specific model I need on the partial page? Should I pass the entire list and then get the first (right now, I only care about the first item in the list - that will EVENTUALLY change, but not any time soon).
Suggestions or thoughts appreciated.
Update: Here is how I accessing the properties on the partial views.
<div class="data-group">
<%: Html.CheckBoxFor(model => model.Property1) %>
<%: Html.LabelFor(model => model.Property1) %>
</div>
Update 2: Per request...
Controller Action (ScenarioController):
public ActionResult Index(int id = 0)
{
if (id == 0)
{
SavedScenario scenario = new SavedScenario();
scenario.AnItemList1.Add(new AnItem1());
scenario.AnItemList2.Add(new AnItem2());
return View("Index", scenario);
}
else
{
SavedScenario scenario = repository.GetScenario(id);
if (scenario == null)
return View("NotFound");
else
return View("Index", scenario);
}
}
[HttpPost]
public ActionResult Index(SavedScenario scenario)
{
if (ModelState.IsValid && TryUpdateModel(scenario, "SaveScenario"))
{
repository.Add(scenario);
repository.Save();
}
return View(scenario);
}
Rendered HTML (I can only include parts of it - this is a small sample of what is in the form):
<form action="/Scenario" id="form0" method="post">
<!-- This is the one that works - the basic Scenario. Top level. -->
<fieldset>
<legend>Scenario Information</legend>
<div class="data-group">
<div class="editor-label">
<label for="ScenarioName">Scenario Name</label>
</div>
<div class="option1">
<input class="wide" id="ScenarioName" name="ScenarioName" type="text" value="" />
</div>
<div class="validation">
<div><span class="field-validation-valid" id="ScenarioName_validationMessage"></span></div>
</div>
</div>
</fieldset>
<!-- This does not work or get submitted (as far as I can tell). -->
<div id="tab2">
<fieldset>
<legend>Tab2</legend>
<div class="data-group">
<input id="Property1" name="Property1" type="checkbox" value="true" /><input name="Property1" type="hidden" value="false" />
<label for="Property1" />
</div>
</div>
</fieldset>
</form>
My apologies for having to keep this so generic.
Hard to guess from this much code. However you should make sure that all properties of your models have the same prefix when they are posted back to the server
Edit: form field names should match property names of your model to correctly bind all values. You have two fields with the same name that you can bind in following way
[HttpPost]
public ActionResult Index(SavedScenario scenario, List<bool> Property1)
{
// here you can do with values coming in property1
if (ModelState.IsValid && TryUpdateModel(scenario, "SaveScenario"))
{
repository.Add(scenario);
repository.Save();
}
return View(scenario);
}
It might be issue with naming the fields on your partial forms. Try naming the fields on your partial views by prefixing it with the name of the Model passed into it...like 'AnItemList1.name' instead of just 'name'..I am just guessing here though...but that's what I did sometimes to fix the problem when I was getting values as null..