Play Framework 1.2.7 mysterious error with form - html

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}" />

Related

Angular 10, Modal not showing propper data until a second object is clicked

If the user clicks in the edit button, it should displays the data in a form inside a modal, however for some reason it needs to click one user, and then another one to show the data. I even tried putting the id from the object in a "h1" tag and it's displaying it correctly in the first click, not sure why.
Here is the first click, as you can see in the console it shows the correct data
And you can even see that the "h1" tag contains the id from the object, but it doesn't show the data in the input tags.
Here is after clicking in another user
It shows all the data correctly after changing to another.
Here are the files that i used.
component.html, this is how i show the data
<input *ngIf="add_modify" type="email" id="name" class="form-control" mdbInput value="{{clicked_user.full_name}}" [(ngModel)]="user.full_name" name="full_name">
<input *ngIf="!add_modify" type="email" id="name" class="form-control" mdbInput [(ngModel)]="user.full_name" name="full_name">
<label for="name">Nombres</label>
<h1 *ngIf="add_modify">{{clicked_user._id}}</h1>
<a (click)="frame.show(); showUserInfo(el)" data-toggle="modal" data-target="#add_user" class="mr-3">
<tr mdbTableCol *ngFor="let el of elements">
<td>{{el.full_name}}</td>
<td>{{el.email}}</td>
<td>{{el.work_station}}</td>
<td>
<a (click)="frame.show(); showUserInfo(el)" data-toggle="modal" data target="#add_user" class="mr-3">
<mdb-icon fas icon="user-edit" class="text-info"></mdb-icon>
</a>
<a (click)="deleteUser()">
<mdb-icon fas icon="user-times" class="text-danger"></mdb-icon>
</a>
</td>
</tr>
Component.ts, this is how i get the data for the clicked user
showUserInfo(user) {
this.clicked_user = user;
console.log(this.clicked_user);
this.add_modify = true;
console.log(this.add_modify);
}
Any sugestions?
I never created the new User(), so it wasn't saving the data correctly, i just made a blank User() at the constructor of the component and it worked just fine.

How can I set a form field as invalid?

I want to validate the length of a field, after removing it's mask. I'm using https://github.com/text-mask/text-mask, and because of that, I can't just use the property "minLength". With the mask that doesn't work. Always has the size expected, even the user just typed one character. Therefore, the need of calling a method in "ngModelChange", clear the mask, and then see the length of the text.
So the question is, how can I set this form field as invalid, if it fails my method validation?
checkDigitosCPF() {
const qtdDigitos = _.replace(this.advogado.cpf, /\D/g, '').length;
this.isCPFNotOk = _.isEqual(qtdDigitos, 11);
}
<div class="form-group">
<label class="form-control-label" for="field_cpf">CPF</label>
<input type="text" class="form-control" name="cpf" id="field_cpf" [(ngModel)]="advogado.cpf" required [textMask]="{mask: cpfMask}" (ngModelChange)="checkDigitosCPF()" minlength="11" />
<div [hidden]="!(editForm.controls.cpf?.dirty && editForm.controls.cpf?.invalid)">
<small class="form-text text-danger" [hidden]="!editForm.controls.cpf?.errors?.required" jhiTranslate="entity.validation.required">
This field is required.
</small>
<small class="form-text text-danger" [hidden]="isCPFNotOk">
Esse campo deve ter no minímo 11 carácteres.
</small>
</div>
</div>
In the component the validator method should look like this:
// this function should be triggered each time the value change or the form submit
validateField(form): void {
if (conditionOfError) {
form.controls.yourFieldName.setErrors({'customLengthError': true})
} else {
form.controls.yourFieldName.updateValueAndValidity()
}
}
In the form html error list:
<small *ngIf="yourFieldName?.errors?.customLengthError">
The error text.
</small>
I solved the question. I got the desired behavior by creating a custom directive.

MeteorJS: How to get id to load from collection

I'm trying to load an array (with simple text) and trying to load it up on the template whenever it is called. How do I get the ID from that specific item to get the array that I stored in it?
HTML Template:
<template name="commentMarker">
<div id="viewMarker">
<h3 id="markerTitle">{{markerName}}</h3>
<h6 id="markerCategory">{{markerCategory}}</h6>
<br>
<fieldset>
<legend>Description</legend>
<p>{{markerDescription}}</p>
</fieldset>
<form id="commentForm">
<fieldset>
<legend>Comments</legend>
<input type="text" id="markerId" name="idForComment" value={{markerId}}>
<textarea rows="3" cols="19" name="comment" id="commentArea" placeholder="Insert your comment here..."></textarea>
{{#each comments}}
<p id="oneComment">{{this}}</p>
{{/each}}
</fieldset>
<input type="submit" value="Comment" class="commentButton">
<input type="submit" value="Close" class="exitButton">
</form>
</div>
</template>
JS:
Template.commentMarker.helpers({
comments(){
alert(template.find("#markerId").value);
if(commentArray.length===0) return;
else return commentArray;
}});
This is where I insert the comment into the collection's item and it's working fine
Template.commentMarker.events({
'click .commentButton': function(e, template){
e.preventDefault();
var id = template.find("#markerId").value;
var comment = template.find("#commentArea").value;
Points.update(id, { $push: { comments: comment }});
commentArray = Points.findOne(id).comments;
template.find("#commentArea").value = ' ';
}
I tried with commentArray as a global variable which still is. But I'm at loss how I can get the Id from that specific item, I even put it's Id (with hidden display) in the form to actually be able to insert the comment. But it doesn't help me with showing the comments because I cannot seem to get to this field in the Template.helpers ...
Not entirely sure what you are trying to do. It's almost like as if you are displaying the comments right after you updated in to the collection. It looks like you are doing this entirely on local and not a online collection.
However, storing it as a session would work...or reactive var. Might not be the best solution tho. Basically replace commentArray = Points.findOne(id).comments; with:
Session.set('comments', Points.findOne(id).comments)
Then to get it out in helpers:
let commentArray = Session.get('comments')
It's not safe to use it all the time tho for sensitive data. Also try catch the findOne(id).comments because it does produce errors if it happen to not find it.
NOTE: If you are going to use Meteor.Methods, you cannot use Session. You have to return the id and find it in your helpers.

Pass data correctly to another dust template

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}

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..