How to read checkbox/radio value in freemarker? - alfresco

I'm working with share forms in alfresco and trying to read the values of ticked checkboxes and checked radio buttons form a form. I extended both the user creation and userprofile form with these input controls and so far I have been unsuccessful at reading the textual values of said controls. Below is a snippet of code:
<div class="row">
<span class="label"><input id="${el}-input-spokenEnglish" type="checkbox" name="spokenLanguages" value="${msg("label.anglais"!"")?html}" /> ${msg("label.anglais")}</span>
<span class="label"><input id="${el}-input-spokenSpanish" type="checkbox" name="spokenLanguages" value="${msg("label.espagnol"!"")?html}" /> ${msg("label.espagnol")}</span>
<span class="label"><input id="${el}-input-spokenGerman" type="checkbox" name="spokenLanguages" value="${msg("label.allemand"!"")?html}" /> ${msg("label.allemand")}</span>
<span class="label"><input id="${el}-input-spokenChinese" type="checkbox" name="spokenLanguages" value="${msg("label.chinois"!"")?html}" /> ${msg("label.chinois")}</span>
<br/>
<span class="label">${msg("label.otherLanguages")} : </span>
<span class="input"><input id="${el}-input-spokenLanguages" type="text" size="30" maxlength="256" value="" <#immutablefield field="spokenLanugages" /> /> </span>
</div>
unfortunately I get nothing so far from whatever is returned and would gladly appreciate some insight into this.fre

If you look at userprofile.get.html.ftl, you'll see the following snippet:
<script type="text/javascript">//<![CDATA[
var userProfile = new Alfresco.UserProfile("${args.htmlid}").setOptions(
{
This means it's triggering a client-side JS file from Alfresco, in this case profile.js (see the head file). So just adding some input fields isn't enough.
You need to extend the client-side JS file.
In the function onEditProfile it gets the Dom elements.
But that's just for showing the actual fiels 'after' it's saved.
In profile.js you'll see: form.setSubmitAsJSON(true); that you have a json object from which you can get your fields.
And in userprofile.post.json.ftl it does a loop on the user.properties:
for (var i=0; i<names.length(); i++)
{
var field = names.get(i);
// look and set simple text input values
var index = field.indexOf("-input-");
if (index != -1)
{
user.properties[field.substring(index + 7)] = json.get(field);
}
// apply person description content field
else if (field.indexOf("-text-biography") != -1)
{
user.properties["persondescription"] = json.get(field);
}
}
user.save();
This probably means that you haven't extended the contentmodel of the cm:person object with your new properties.

Related

Materialize css modal validation

I am using Materialize css to design my post. Suppose I have a form in modal and I and post it to server.
In that form I am checking if all fields are having value.
<form>
<div class="input-field">
<input type="text" id="title" class="validate" required="" aria-required="true">
<label for="title">Title</label>
</div>
The title field is required. But when I click on a submit button in modal it is closing even if title field has empty value. Is there any way to keep the modal open for validation error in Materialize css v1.
Think about this is in separate steps. The form submission only takes place at the end of the chain, when our criteria have been met.
User Submits form
We check the form
We feedback to user
Depending on the results of 2, we may either go back to step 1, or on to step 3.
Modal Structure:
<div id="modal1" class="modal">
<div class="modal-content">
<div class="input-field">
<input type="text" id="title" class="validate" required="" aria-required="true">
<label for="title">Title</label>
<span class="helper-text" data-error="Please enter your name" data-success="Thankyou!"></span>
</div>
</div>
<div class="modal-footer">
<a id="submit-button" href="#!" class="btn">Submit</a>
close
</div>
</div>
We add optional helper-text span for user feedback, as per the documentation.
The Javascript:
document.addEventListener('DOMContentLoaded', function() {
// init modal
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
// get button
var button = document.querySelector('#submit-button');
// Run our own function when clicked
button.addEventListener("click", checkForm);
// Function checks for input
function checkForm() {
var input = document.querySelector('#title');
if(input.value) {
// submit form
// add valid class to show helper
input.classList.add('valid');
// close modal
instances[0].close();
// clear form
input.value = '';
// remove valid class
input.classList.remove('valid');
} else {
// prompt user for input
input.classList.add('invalid');
}
}
});
We grab the value of the text input, and based on that, add a valid or invalid class - this is the built in materialize stuff that hides or shows the relevant message that we set in data-error and data-success.
The only thing you need to add to this is the actual form submission - so something like form.submit().
Codepen.

How to find the default tab index of controls?

I want to find the default tab index of the form.
I have not given but still all the control has the tab index. I want to find that default tab index through the j query. How can i find that?
Jquery and tab-index
The way tabindexing works is that it goes trough your html markup and looks for tabable elements.
So say you have this code:
<form>
<label>Name:</label>
<input type="text" />
<br>
<input type="submit" />
</form>
The text input will be tabbed first, and then the submit input.
Yes i know this how do it get the tabbing?
$(function() {
$firstinput = $("form").find("input")
console.log($firstinput.first()); //prints the first element thats an input.
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<label>Name:</label>
<input type="text" />
<br>
<input type="submit" />
</form>
The code above will only work if you only have input elemtns and add not trickery to the markup like hiding your elements etc.
In the code below im using the jquery UI :focusable selector.
With this you should get the first tabbable element in your form
//:focus selector from jquery UI
$.extend($.expr[':'], {
focusable: function(element) {
var nodeName = element.nodeName.toLowerCase(),
tabIndex = $.attr(element, 'tabindex');
return (/input|select|textarea|button|object/.test(nodeName) ? !element.disabled : 'a' == nodeName || 'area' == nodeName ? element.href || !isNaN(tabIndex) : !isNaN(tabIndex))
// the element and all of its ancestors must be visible
// the browser may report that the area is hidden
&& !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
}
});
//actual code
$(function() {
$form = $("form");
$first = $form.find(":focusable").first();
console.log($first);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<label tab-index="0">Name:</label>
<input type="text" />
<br>
<input type="submit" />
</form>
You can search for 'tabindex' attribute with jquery.
var tabindexVal = $('selector').attr('tabindex');

CSS for Form Field Errors

We have a three dropdown date of birth field in our form, which, right now is producing three separate error messages if the fields are left blank and user clicks submission.
We would like to either make it just one of those error messages, or show some other display beneath the submission button.
Any guidance would be fantastic!
Although not mentioned, I'd have to imagine you're using JavaScript to validate the form, and if so, try something like the following, whereby in your HTML you have a single span tag (or p) that's accessible via an id tag (like #error or something). In your JavaScript, simply set the #error tag to whichever error was last seen by the JavaScript. As you'll note below, if both "birth date" and "name" are missing, the span tag will only display the missing name error text. That said, you could easily concatenate the strings if need be.
Pseudocode (JS)
function validateForm() {
var isValid = true,
var myErrorText;
if (birth date is missing) {
isValid = false;
errorText = "You must enter a birth date";
}
if (name is missing) {
isValid = false;
errorText = "You must enter a name";
}
// Display the error message if the form is invalid
if (!validForm) {
$('span#error').text(myErrorText);
}
return validForm;
}
HTML
<form method="post" action="/whatever" onSubmit="return validateForm()">
<input type="text" id="birthDate" name="birthDate" >
<input type="text" id="name" name="name">
<button type="submit" id="submit" class="btn">Submit</button>
</form>
<span id="error"></p>

knockout.js boolean data-binding issues with radio buttons

I'm currently doing the following to compensate for boolean's not mapping well to radio buttons. I am stuck binding 1 and 0 to the value (instead of true and false) because of how the fields are read out of the observables. The value of Pref1/Pref2 come as true/false boolean values from the server. The key here is I want to not only data-bind the checked value of the radio button to match the true/false in the object, but I also want the boolean value of true/false to be written back into the GraduationClass object. My compensation code is not only ugly, but not scalable.
<input type="radio" value="1" name="radioGroup" data-bind="checked: Pref1" />Yes
<input type="radio" value="0" name="radioGroup" data-bind="checked: Pref2" />No
Save
function SiteSettingsViewModel() {
var self = this;
this.saveGraduationClass = function(graduationClass) {
// hack until i get a custom radio button binding
if (graduationClass.Pref1() == 1) {
graduationClass.Pref1(true);
} else {
graduationClass.Pref1(false);
}
if (graduationClass.Pref2() == 1) {
graduationClass.Pref2(true);
} else {
graduationClass.Pref2(false);
}
// ...ajax call to save graduationClass to the server
}
function GraduationClass(data) {
var self = this;
ko.mapping.fromJS(data, {}, this);
}
Here is example from knockoutJs website, that demonstrate how to use radio buttons with
"checked" attribute:
<p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam" /></p>
<div data-bind="visible: wantsSpam">
Preferred flavor of spam:
<div><input type="radio" name="flavorGroup" value="cherry" data-bind="checked: spamFlavor" /> Cherry</div>
<div><input type="radio" name="flavorGroup" value="almond" data-bind="checked: spamFlavor" /> Almond</div>
<div><input type="radio" name="flavorGroup" value="msg" data-bind="checked: spamFlavor" /> Monosodium Glutamate</div>
</div>
<script type="text/javascript">
var viewModel = {
wantsSpam: ko.observable(true),
spamFlavor: ko.observable("almond") // Initially selects only the Almond radio button
};
// ... then later ...
viewModel.spamFlavor("msg"); // Now only Monosodium Glutamate is checked
</script>
But I dont understand why you use two objects - "Pref1" and "Pref2" fro one radiobutton group "radioGroup"? In this case you just could use one object as in an example used "spamFlavor".
So, please, describe more ditaily what you want to bind: one radiobuttons group by one selected value, or something else.
Also you could use computed observables to calculate different values, please see example.

Play Framework How can i pass collection to action create()?

I am starter with Play Framework. I got a problem when i passed parameters.
I want to pass a collection from view to controller. And i do not know how to do this. I always get "null" when i get a collection from view.
My code below:
Code in controller:
public static void create(List<Book> books) throws Exception {
for(Book book : books){
System.out.println(book.get(0).author) // i got null :(
}
}
Code in HTML
Book 1:
<input type="text" name="books.author" />
<input type="text" name="books.title" />
Book 2:
<input type="text" name="books.author" />
<input type="text" name="books.title" />
When i submit, i want to add 2 records into database include Book1 and Book2. Please support me
Thanks
You can make this work by simplying add the array indicator to your HTML code
Book 1:
<input type="text" name="books[0].author" />
<input type="text" name="books[0].title" />
Book 2:
<input type="text" name="books[1].author" />
<input type="text" name="books[1].title" />
I have tested this solution, and it works fine.
Also note that your println will not compile, as you are calling get(0) on the Book object, and not the List object. If you just println book.author, it outputs the author as required.
In case anyone needs an example of the Javascript for dyanmically adding and removing books (JQUERY needed):
<script type="text/javascript">
$(document).ready(function() {
var bookCount=0;
$('#btnAddBook').click(function() {
bookCount++;
//newElem = go up a to the parent div then grab the previous container
var newElem = $(this).parent().prev().clone().attr('id', 'book[' + bookCount + ']');
//for each input inside the div, change the index to the latest bookCount
$(newElem).find("input").each(function(){
var name = $(this).attr('name');
var leftBracket = name.indexOf("[");
var rightBracket = name.indexOf("]");
var beforeBracketString = name.substring(0,leftBracket+1);//+1 to include the bracket
var afterBracketString = name.substring(rightBracket);
$(this).attr('name', beforeBracketString + bookCount + afterBracketString);
});
//insert it at the end of the books
$(this).parent().prev().after(newElem);
$(newElem).find("input").each(function(){
$(this).attr('id', $(this).attr('id') + bookCount);
});
//enable the remove button
$('#btnRemovebook').removeAttr('disabled');
//If we are at 16 divs, disable the add button
if (bookCount == 15)
$(this).attr('disabled','disabled');
});
$('#btnRemoveBook').click(function() {
bookCount--;
//remove the last book div
$(this).parent().prev().remove();
//in case add was disabled, enable it
$('#btnAddbook').removeAttr('disabled');
//never let them remove the last book div
if (bookCount == 0)
$(this).attr('disabled','disabled');
});
});
</script>
<!-- HTML Snippet -->
<div id="book[0]">
<label> Book: </label>
<input type="text" name="books[0].author" value="Author" />
<input type="text" name="books[0].title" value="Title" />
</div>
<div>
<input type="button" id="btnAddbook" value="Add another book" />
<input type="button" id="btnRemovebook" value="Remove last book" disabled="disabled" />
</div>
<!-- REST of the HTML -->

Resources