simple database query in lift framework web page - lift

I'm starting out with Lift and been reading a few tutorials and books that are available online. Coming from a JSP (or GWT) background, it's a huge leap, especially since I'm still learning Scala too.
Anyway... I've created the basic site by downloading the lift tar.gz stuff from their site, copied the lift_blank" directory and renamed it to "test". Did the whole "sbt update ~jetty-run" thing etc etc.
What I want to do is modify the "index.html" page to simply have a text field for input, and a button that says "search". Basic idea, you type your firstname, hit "Search", a database query is executed for finding records with a firstname of "what-you-entered-in-the-text-field", and then the results are formatted and displayed on the web page; after the page has refreshed, the text field needs to contain the name that was entered as well.. You type in a different name, hit "search", and new results are displayed on the page. Initially (first time visiting the page), the results are of course empty. Simple stuff...
However, the examples I've all seen use html forms and POST backs etc; I really dislike this, for example users get all flustered when refreshing the page and they get a firefox popup "To display this page, Iceweasel must send information that will repeat any action (such as a search or order confirmation) that was performed earlier."... the page is also refreshed which is something I'd like to avoid.
Previously when I would build this in JSP, I would use all javascript; no "form" tags or anything, just a simple field with javascript events for hitting enter or hitting a "button"... events thaen get channeled to a main javascript function "onQuery" which then creates an AJAX request; when the result comes back from the server, javascript would modify a wrapper "div" element by changing the "innerHTML" value etc. The nice thing here is that the page doesn't refresh, just a tiny subsection of it does, the "table" (actually a div) which holds the results.
How would I re-create a very similar thing in Lift? I'm kind of lost here. I've followed a few examples in the past few days, but again they all use POST / forms. I can handle the scala database querying, and I understand how Lift's templates works, it's just the snippet / comet stuff that I could use a few pointers on.

You can try to use the SHtml.ajaxText function to get the input and to use Wiring on server's side to deal with the request and change automatically the result.
However, with this solution, you no longer need the submit button, but as you don't want a form it should not matter much.
Here is what I think about for the HTML file :
<div id="myHtml" class="lift:surround?with=default;at=content">
<form class="lift:form.ajax">
<input class="lift:SearchForm.name"/>
</form>
Value searched : <span class="lift:SearchForm.display">
</div>
Now on server's side it is a little bit more complicated
class SearchForm{
val name = SHtml.ajaxText("", s=>{ SearchWiring.name.set(s); Noop})
def display = {
WiringUI.apply(SearchWiring.name)(name:String => {"*" #> name} )
}
}
object SearchWiring{
val name = ValueCell("All")
}
I don't know if this is totally rigorous but it is my best thought for your problem. You will find more details about wiring on the official liftweb demo and on Seven Things blog. I hope it will help!

Below is what I ended up using. The one thing I dislike about Lift is all the "magic" that needs to be inserted at various points. I can understand most of this, but the whole " ++ hidden" thing could use some explaining...
The "index.html" page, everything including the "body" tag:
<body class="lift:content_id=main">
<div id="main" class="lift:surround?with=default;at=page">
<lift:Search.search>
Search Query: <query:text/> <query:button/><br/>
<div id="results">
</div>
</lift:Search.search>
</div>
</body>
The "Snippet" code, in a class called "Search.scala" (some of the import statements are unused, a leftover result of attempting different approaches):
package code
package snippet
import scala.xml.{NodeSeq, Text}
import net.liftweb.util._
import net.liftweb.common._
import java.util.Date
import code.lib._
import Helpers._
import common.Main
import common.solr.{Hitlist, Solr}
import net.liftweb.http.{S, StatefulSnippet, SHtml}
import net.liftweb.http.js.JsCmds.SetHtml
import _root_.net.liftweb.http.SHtml._
import _root_.net.liftweb.util.Log
import net.liftweb.http.js.JsCmd
import net.liftweb.http.js.JE.JsRaw
object Search {
def search(xhtml:NodeSeq):NodeSeq = {
var queryText = "(initial)"
def runQuery() = {
println("\n\nQuery: " + queryText)
SetHtml("results", <span>Query: {queryText}</span>)
}//runQuery
ajaxForm(
bind("query", xhtml,
"text" -> text(queryText, queryText = _),
"button" -> submit("Post", runQuery)
) ++ hidden(runQuery _)
)
}//search
}//Search

Related

Prestashop module development - why is this template redirecting not working

On user-registration confirmation I want to show a simple popup. For the moment, in order to simplify I'm happy to show an "Hello World".
This is the template file, views/templates/hook/registrationConfirm.tpl
<div id="idname" class="block">
<h1 class="title_block">HelloWorld</h1>
</div>
In my custom module I have this hook (which I know is being triggered doing debug):
public function hookActionCustomerAccountAdd($params) {
return $this->display(__FILE__, 'registrationConfirm.tpl');
}
It doesn't show anything (I also tried inspect the source code of the rendered page, but I dind't find the "HelloWorld")
Hooks starting by "Action" react to an action but do not display anything, but those starting with "Display" do.
You should also react to the hook displayCustomerAccount
public function hookActionCustomerAccountAdd() {
$this->is_new_account = true;
}
public function hookDisplayCustomerAccount()
{
if ($this->is_new_account) {
return $this->display(__FILE__, 'registrationConfirm.tpl');
}
}
I tried the solution posted by #shagshag but for some reason it doesn't work for me. So I share my solution (it's not pretty, nor efficient I think, but it seem to work for me): in the hookActionCustomerAccountAdd I save on a custom table (newCustomersTmp) email and customer id, because these are the data I need after, in the display Hook. Then in the hookDisplayCustomerAccount I check if an user with the current email ($this->context->customer->email) already exists in my table: if so I retrieve the data, do the actions I need with them and delete the row in the table.

Parameter and view naming collisions in Play/Scala templates

I am new to Play Framework and still trying to wrap my head around some things with the new Scala template engine.
Let's say I have the following package structure:
app/
app/controllers/Items.scala
app/models/Item.scala
app/views/layouts/page.scala.html
app/views/item/show.scala.html
app/views/item/details.scala.html //partial
And this is my item/show template:
#(item: Item, form: Form[Item])(implicit flash: Flash)
#layout.page() {
#*want to include details partial, wont work due to item param*#
#item.details(item)
}
Since including another template (e.g. including item/details above) is the exact same syntax as accessing a template parameter (e.g. item above), obviously this existing naming convention won't work without something changing.
I know I can rename my "app.views.item" package to "app.views.items", and rely on singular/plural forms to differentiate the view from the param name, but this does not seem like a very straightforward solution. Also what if I really want the parameter name to be the same as the view package?
One idea I have is to prepend all my views with an extra top level package:
app/views/views/item/details.scala.html
So the include syntax would be #views.item.details(), but again this is obviously a hack.
What is a good way to avoid this issue? How can I better organize my code to avoid such naming collisions?
Most other template engines use operations like "include" or "render" to specify a partial include. I don't mean to offend anyone here, but is the Play Scala template engine syntax so terse that it actually dictates the organization of code?
3 solutions:
First
Typpicaly for partial templates you should use tags as described in the docs, where app/views/tags folder is a base:
file: app/views/tags/product.scala.html
in the templates (no initial import required in the parent view full syntax will allow you to avoid name-clash: #tags.packageName.tagName()):
<div id="container">
#tags.product(item)
</div>
Of course in your case you can also use packages in the base folder
file: app/views/tags/item/product.scala.html
<div id="container">
#tags.item.product(item)
</div>
I'm pretty sure that'll solve your problem.
Second
To avoid clash without changing package's name you can just rename the item in your view, also I recommend do not use a form name for the Form[T] as it can conflict with helpers:
#(existingItem: Item, existingItemForm: Form[Item])(implicit flash: Flash)
#layout.page() {
#item.details(existingItem)
}
Third
If you'll fill your Form[Item] before passing to the view with given Item object, you don't need to pass both, as most probably you can get data from the form:
#(itemForm: Form[Item])(implicit flash: Flash)
#layout.page() {
<div>Name of item is: #itemForm("name").value (this is a replacemnet for ##existingItem.name </div>
#item.details(itemForm)
}
Of course in you product.scala.html you'll need to change the #(item: Item) param to #(itemForm: Form[Item])

Creating a custom field constructor in Play 2 (scala)

I am trying to grok the instructions given in the play 2 scala tutorial for form template helpers. I am getting stuck in the section "Writing your own field constructors". It gives a sample template (without saying what the name of the file should be):
#(elements: helper.FieldElements)
<div class="#if(elements.hasErrors) {error}">
<label for="#elements.id">#elements.label</label>
<div class="input">
#elements.input
<span class="errors">#elements.errors.mkString(", ")</span>
<span class="help">#elements.infos.mkString(", ")</span>
</div>
</div>
Then it shows this code:
object MyHelpers {
implicit val myFields = FieldConstructor(myFieldConstructorTemplate.f)
}
I am confused about how this is supposed to relate to the template. (eg, is the template file supposed to be called myFieldConstructorTemplate.scala.html?) I tried some variations on this without luck.
I'm new to both scala and Play, but I also know play 2 and its docs are new, so I'm not sure what incredibly obvious thing I'm missing.
thanks!
I've just had the same problem, I agree with you the documentation is not clear at all...
Possible error 1
not found: value FieldConstructor
It means that you haven't imported the helper with this instruction :
#import helper._
Possible error 2
not found: value implicitConstructor
It means that you are declaring the field constructor in the wrong place in your template (i.e. : in the #helper.form method). To fix this, I declared my field constructor just after my import instructions :
#import form._
#import helper._
#implicitConstructor = #{ FieldConstructor(foundation_field.render) }
(My foundation_field.scala.html file is in the views.form package).
In the tutorial this code is along the text:
Often you will need to write your own field constructor. Start by
writing a template like:
This means you have to create your own template (xxxx.scala.html) and add that code inside. After that, you import it in your template with the code they provide (remember to add that to each scala template that uses your custom field):
#implicitField = #{ FieldConstructor(xxxx.f) }
Check the samples of Play, the Forms sample uses a similar approach with Twitter bootstrap.
To follow the logic of Scala implicit keyword, the document is implicit too ;)
Scala and Play are too immature right now, for that reason the documentation is very poor.
This SOF answer is very good: https://stackoverflow.com/a/15268122/1163081
You can also check the Play source for more examples: https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/html/
Or this guys appears to discover the solution: https://groups.google.com/forum/#!msg/play-framework/2e1EqZJ-Qks/gXD1oo0IjfcJ

question about CodeIgniter urls

I am using an application (a blog) written using the CodeIgniter framework and would like to search my blog from my browsers location bar by adding a string to the end of my blogs url like this:
http://mysite.com/blog/index.php/search...
As you can see in the example above I am not really sure how to format the rest of the url after the search part so I am hoping someone here might be able to point me in the right direction.
This is what the form looks like for the search box if that helps at all.
form class="searchform" action="http://mysite.com/blog/index.php/search" method="post">
<input id="searchtext" class="search_input" type="text" value="" name="searchtext">
<input type="submit" value="Search" name="Search">
</form>
Thx,
Mark
Since your form is posting to http://mysite.com/blog/index.php/search, I'm assuming this 'search' controller's default function is the one your are attempting to submit your data to. I think that the easiest way to do this would be to just grab the post data inside of the controller method you're posting to. Example:
function search()
{
$search_params = $this->input->post('search_text');
}
Then you would have whatever the user input stored as $search_params, and you can take actions from there. Am I misunderstanding what you're asking?
It seems like you're kind of discussing two different approaches. If you wanted to make a request to
mysite.com/blog/index.php/search&q=what_I_am_looking_for
This is going to call the search controllers default method (which is index by default). If you wanted to use the URL to pass parameters like that you would go to your function in the search controller and do:
print_r($this->input->get('q'));
This will print out "what_am_I_looking_for".
An easier approach in my opinion would be to:
1. Create a view called "search_view" with the HTML content you pasted above, and have the form "action" http://www.mysite.com/blog/index.php/test/search
Create a controller called "Test" that looks like the following:
class Test extends CI_Controller {
function search()
{
$search = $this->input->post('searchtext');
print_r($search);
}
public function display_search()
{
$this->load->view('search_view');
}
}
Visit http://www.mysite.com/blog/index.php/test/display_search in your browser. This should present you with the form you placed in search_view.php. Once the form is submitted, you should be sent to the search function and print out the variable $search, which will have whatever text you submitted on that form.
If this isn't what you were looking for then I am afraid I do not understand your question.

How do I keep focus on a textbox using Lift (the Scala framework)?

Pardon my excruciatingly simple question, but I'm quite new to the world of Lift (and Scala, for that matter).
I'm following the "Getting Started" tutorial on the Lift website: http://liftweb.net/getting_started
I've got it up and running but I'd like to make a quick modification to the app so that every time I press enter in the textbox, it maintains focus. I've managed to get it to focus on page load using FocusOnLoad but I can't quite figure out how to get it to keep focus (using only Lift's classes, no custom JavaScript).
Here's what my def render method (the bind part) code looks like:
def render =
bind("chat", // the namespace for binding
"line" -> lines _, // bind the function lines
"input" -> FocusOnLoad(SHtml.text("", s => ChatServer ! s)) )
So that works for getting it to focus upon page load. But since this is a Comet app, the page only loads once.
All my other code looks exactly like the tutorial FWIW.
The render method in a CometActor only gets called when the CometActor is first initialized, which happens when the user first goes to the Chat page. Afterwards, the page updates usually happen inside of the lowPriority or highPriority methods. So if you want the text box to become focused after the user sends an AJAX update to the CometActor, you should add it to one of those methods. An example which uses JQuery would be this:
override def lowPriority = {
case m: List[ChatCmd] => {
val delta = m diff msgs
msgs = m
updateDeltas(delta)
partialUpdate((JqJE.Jq(JE.Str("input[type=text]")) ~> (new JsRaw("focus()") with JsMember)).toJsCmd)
}
}
I haven't tried compiling this, so it might need some slight tweaking. Essentially, it's just sending another JavaScript command to the browser that uses JQuery to find a text input on the page and then sets the focus on that control. If there are multiple text inputs, you'll need to modify the class on the HTML template for the control you want to set focus on, then make sure that you change your render method to be:
def render =
bind("chat",
"line" -> lines _,
"input" -%> FocusOnLoad(SHtml.text("", s => ChatServer ! s)) )
The -%> method instructs Lift to not ignore any attributes in the template during the bind phase. Then you can modify the JQuery selector to use that class to find the right control to focus on. Part of the form security in Lift obscures the ID assigned to forms and their controls to prevent XSS attacks, so it's generally better to use class selectors to find form controls using JQuery or some other Javascript framework.