Radio button in Lift? - scala

I'm trying to render a radio button choice in my webapp but I have some problems.
What I have done is to try jcern solution posted in this answer:
get checkbox and radio button value in lift
This is my HTML code:
<div class="lift:Radio.render">
<input id="choice" name="choice" type="radio"/>
</div>
And this is my SCALA code:
object Radio {
def render = {
val radioChoices = List("Choice_1", "Choice_2")
var choice:Box[String] = None
"name=choice" #> SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp))
}
}
But the compiler give me an error on binding:
could not find implicit value for parameter computer:net.liftweb.util.CanBind[net.liftweb.http.SHtml.ChoiceHolder[String]]
[error] "#choice" #> SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp))
[error] ^
I have to bind with .toForm to pass compile like this:
"name=choice" #> SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp)).toForm
The problem is that no radio buttons are displayed on my web page, nothing at all..
Am I doing something wrong? I can't see it. And why the first solution (without .toForm) give me an error at compile?

The reason is that SHtml.radio and SHtml.radioElem return a ChoiceHolder instead of a the NodeSeq that most other items in SHtml do - as you can see in the API Doc. Because of that, you need to call .toForm or render the output yourself.
Returning the ChoiceHolder allows you to customize how each item is displayed, so you can add custom text for the label, etc... If the basic toForm output didn't work for you, you could do something like:
val choices = SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp))
"#choice" #> choices.items.zipWithIndex.map { case(itm, pos) =>
val rId = "myId-%s".format(pos)
<div class="radio">{
//We'll add a custom ID attribute to the radio button
itm.xhtml.asInstanceOf[Elem] % ("id", rId)
}<label for={ rId }>{
//Output the toString or use some other method to output a label
itm.toString
}</label>
</div>
}
You can find more information on customizing the radio buttons in the Lift Cookbook.
As for why your CSSSelector is not outputing anything, I am not sure. The code snippet you were trying worked for me. The screenshot below illustrates the output I see with the toForm method.

Related

How can I test if a html input type radio is checked

I have this HTML in my component.html:
<input type="radio" [checked]="selected" (change)="select()" />
How can I make a Spectator query and expect to test if this input element is checked or not?
I have tried with:
expect(spectator.query('input')).toHaveAttribute('checked');
But I get the error:
Error: Expected element to have attribute 'checked', but had 'undefined'
And I have tried with:
expect(spectator.query('input')).toBeChecked();
But then I get the error:
Error: Expected element to be checked
How can I test this simple HTML input element?
Thank you
Søren
expect(spectator.query('input')).toBeChecked(); is the correct usage.
It looks like selected property is false due to which radio button is not selected and you are getting this error. Simple fix you binding in test (by setting selected to true) or update assertion to check if radio button is not selected:
expect(spectator.query("input[type=radio]")).not.toBeChecked();
Take a look at this stackblitz code sample where I have 2 bound radio buttons one selected and another not selected and I have tests for it.
it("should be checked", () => {
spectator = createComponent();
expect(spectator.query("#r1[type=radio]")).not.toBeChecked();
});
it("should not be checked", () => {
spectator = createComponent();
expect(spectator.query("#r2[type=radio]")).toBeChecked();
});
Also, take a look at this guide to see available custom matchers.

How to fix the red mark that appears when using binding.scala in intellij?

I am developing with scalajs and binding.scala. I'm using the IDE as an Intellij. However, when using dom macro in Intellij, the following red mark appears. this error appears when I use the attribute value of id in the input element as macro What is the solution?
This error(a.k.a. "cannot resolve symbol something") appears when you use the id attribute value of the input element as marco.
please see the link of image below.
this is my code image.
#dom
def render: xml.Elem = {
val name: _root_.com.thoughtworks.binding.Binding.Var[_root_.java.lang.String] = Var.apply("Binding.scala")
val show: _root_.com.thoughtworks.binding.Binding.Var[Boolean] = Var.apply(false)
<div>
<p>
<label for="showCheckbox">
<input type="checkbox" id="showCheckbox" onchange={e: Event => show.value = showCheckbox.value }/>
<span> Say hello to <input id="nameInput" value={name.value} oninput={_: Event => name.value = nameInput.value}/></span>
</label>
</p>
{
if (show.bind) {
<p>
Hello, {name.bind}!
</p>
} else {
<!-- Don't show hello. -->
}
}
</div>
}
I actually have the same problem. I have 2 ways dealing with it:
Ignore these exception - as they are only a problem within IntellIJ
(it compiles just fine).
Use for example JQuery like this:
import org.scalajs.jquery.jQuery
..
jQuery("#showCheckbox").value()
As soon as your id gets more dynamic - you will need something like that anyway (at least that is what I know;)) -> jQuery(s"#${elem.id}").value().
You could take advantage of the scalaJS Event passed in, maybe something like:
oninput={ev: Event => name.value = ev.target.asInstanceOf[HTMLInputElement].value}

jquery / ajax form not passing button data

I thought the HTML spec stated that buttons click in a form pass their value, and button "not clicked" did not get passed. Like check boxes... I always check for the button value and sometimes I'll do different processing depending on which button was used to submit..
I have started using AJAX (specifically jquery) to submit my form data - but the button data is NEVER passed - is there something I'm missing? is there soemthing I can do to pass that data?
simple code might look like this
<form id="frmPost" method="post" action="page.php" class="bbForm" >
<input type="text" name="heading" id="heading" />
<input type="submit" name="btnA" value="Process It!" />
<input type="submit" name="btnB" value="Re-rout it somewhere Else!" />
</form>
<script>
$( function() { //once the doc has loaded
//handle the forms
$( '.bbForm' ).live( 'submit', function() { // catch the form's submit event
$.ajax({ // create an AJAX call...
data: $( this ).serialize(), // get the form data
type: $( this ).attr( 'method' ), // GET or POST
url: $( this ).attr( 'action' ), // the file to call
success: function( response ) { // on success..
$('#ui-tabs-1').html( response );
}
});
return false; // cancel original event to prevent form submitting
});
});
</script>
On the processing page - ONLY the "heading" field appears, neither the btnA or btnB regardless of whichever is clicked...
if it can't be 'fixed' can someone explain why the Ajax call doesn't follow "standard" form behavior?
thx
I found this to be an interesting issue so I figured I would do a bit of digging into the jquery source code and api documentation.
My findings:
Your issue has nothing to do with an ajax call and everything to do with the $.serialize() function. It simply is not coded to return <input type="submit"> or even <button type="submit"> I tried both. There is a regex expression that is run against the set of elements in the form to be serialized and it arbitrarily excludes the submit button unfortunately.
jQuery source code (I modified for debugging purposes but everything is still semantically intact):
serialize: function() {
var data = jQuery.param( this.serializeArray() );
return data;
},
serializeArray: function() {
var elementMap = this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
});
var filtered = elementMap.filter(function(){
var regexTest1= rselectTextarea.test( this.nodeName );
var regexTest2 = rinput.test( this.type ); //input submit will fail here thus never serialized as part of the form
var output = this.name && !this.disabled &&
( this.checked || regexTest2|| regexTest2);
return output;
});
var output = filtered.map(function( i, elem ){
var val = jQuery( this ).val();
return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}).get();
return output;
}
Now examining the jQuery documentation, you meet all the requirements for it to behave as expected (http://api.jquery.com/serialize/):
Note: Only "successful controls" are serialized to the string. No submit button value is serialized since the form was not submitted using a button. For a form element's value to be included in the serialized string, the element must have a name attribute. Values from checkboxes and radio buttons (inputs of type "radio" or "checkbox") are included only if they are checked. Data from file select elements is not serialized.
the "successful controls link branches out to the W3 spec and you definitely nailed the expected behavior on the spec.
Short lame answer: I think it is teh broken! Report for bug fix!!!
I've run into a rather unusual issue with this. I'm working on a project and have two separate php pages where one has html on the page separate from the php code and one is echoing html from inside php code. When I use the .serialize on the one that has the separate html code it works correctly. It sends my submit button value in its ajax call to another php page. But in the one with the html echoed from the php script I try to do the same thing and get completely different results. It will send all of the other info in the form but not the value of the submit button. All I need it to do is send whether or not I pushed "Delete" or "Update". I'm not asking for help (violating the rules of asking for help on another persons post) but I thought this info might be helpful in figuring out where the break down is occurring. I'll be looking for a solution and will post back here if I figure anything out.

Not-in-the-same-line radiobutton values

I'm building a "buffet menu list" form which has a lot of options for the "menu" radiobutton.
However I noted that all those values are "inline" just like in this example: http://demo.atk4.com/demo.html?t=14
I'd like to know in first instance how could I add a line break on every value, and then, how could I simulate groups by adding some sort of < p> < /p> between specific option values (logical grouping).
Thanks in advance!
There are two solutions I can think of.
Look at the examples here for some inspiration:
http://agiletoolkit.org/doc/grid/columns
1. Adding custom field to grid
First, create a form with no mark-up:
$form = $this->add('Form',null,null,array('form_empty'));
Next, add Grid into a form like this:
$grid = $form->add('Grid'); // or MVCGrid if you are using models
Add a column for selection:
$grid->addColumn('template','selection')
->setTemplate('<input type=radio name=selection value="<?$id?>"/>');
Finally - make sure the column 'selection' is first (or last)
$grid->addOrder()->move('selection','first')->now();
Finally you need to manually look into the POST data, because it's not a real form column.
if($form->isSubmitted()){
$this->js()->univ()->successMessage('Selection is '+((int)$_POST['selection']))
->execute();
}
You must remember that accessing POST directly exposes you to injection attack and you must validate it properly. Grid also MUST be inside the form, however you can place submit button anywhere else on your page. You can also use "Form_Plain", see "http://agiletoolkit.org/whatsnew" for an example.
2. Using JavaScript and hidden field
In this example you can add a bunch of Radio button elements and tie them to a form. I've also using "Lister" here instead of "Grid", of course you can mix-and-match those approaches.
$form = $this->add('Form');
$selection = $form->addField('line','selection');
// can be placed anywhere.
$menu = $this->add('MVCLister',null,null,array('view/menu'));
$menu->setModel('MenuItems');
$menu->js(true)->find('input[type=radio]')->click(
$selection->js()->_enclose()->val(
$this->js()->_selectorThis()->val()
);
);
// produces $('#menu_id').find('input[type=radio]').click(function(){
// $('#selection_id').val( $(this).val() );
// }
Your view/menu.html template file could look like this:
<div class="menu-container">
<?rows?><?row?>
<div><input type="radio" name="anything" value="<?$id?>"> <?$name?> </div>
<?/row?><?/rows?>
</div>
EDIT: code which worked for Fernando
$grid->addColumn('template','Menu')
->setTemplate('<input type=\'radio\' name=\'selection\' value="<?$value?>"/> <?$value?>');
if($form->isSubmitted()){
$this->js()->univ()
->successMessage('Hoy: <b>'.$_POST['selection'].'</b>')->execute();
}

Lift CometActor: Organizing HTML generated by render and fixedRender

I'm trying to build a simple search application as an learning experiment with Comet and the Lift Framework. The plan is to have a page with a text entry and space for search results. When a search term is entered, it should be transmitted as an ajax request and the results should be pushed back by the server and rendered on the same page. When the server finds more results, they should be pushed to the client.
Using the Comet Chat Demo as template, I have a CometActor that renders both an ajax form and the search results from the following template:
<lift:comet type="SearchResults" name="Other">
<search:input><search:input /><input type="submit" value="Search" /></search:input>
<search:results>
<div>Results for: <search:tag /></div>
<div class="search-results">
<search:list>
<li><list:title /></li>
</search:list>
</div>
</search:results>
</lift:comet>
The corresponding SearchResults actor renders this in two parts: fixedRender generates the ajax form and render is responsible for rendering the search results.
class SearchResults extends CometActor {
override lazy val fixedRender: Box[NodeSeq] = {
SHtml.ajaxForm(bind("search", findKids(defaultXml, "search", "input"),
"input" -> SHtml.text("", updateSearch _)))
}
private def updateSearch(tag: String) = Log.info("UpdateSearch: " + tag)
def render = {
bind("search", findKids(defaultXml, "search", "results"),
"tag" -> "MyTag", // TODO show actual search tag
"list" -> <ul><li>Entry</li></ul>) // TODO actual search results
}
}
In principle this code works, but it renders the search box below the results not on top where I would expect it.
I assume, this has to do with the oder in which render and fixedRender are executed. How can change this code to have the search box at the top?
Have a look at CssSelectors. But i guess this question is obsolete by now ;) Also CssSelectors weren't available back in 09.