Help with idMemoize

76 views
Skip to first unread message

Shafique Jamal

unread,
May 12, 2015, 10:28:24 AM5/12/15
to lif...@googlegroups.com
Help with idMemoize

Hello, I'm trying to create a snippet for a seach form that returns results via an ajax call, so that the entire page does not reload. I have checked the following sources already (but still can't figure this out):


Here is the HTML:

<form data-lift="form.ajax">
                <div data-lift="PackageSearch.search">
                    <input type="text" name="packagenumber" placeholder="packagenumber"/>
                    <input type="submit">

                    <div id="result">(for test & debug) Your package number will be echoed here.</div>

                    <table class="table table-bordered table-hover table-striped">
                        <thead>
                        <tr>
                            <th>Package Number</th>
                            <th>Some field 0</th>
                            <th>Some field 1</th>
                            <th>Some field 2</th>
                            <th>Some field 3</th>
                            <th>Some field 4</th>
                            <th>Some field 5</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr>
                            <td></td>
                        </tr>
                        </tbody>
                    </table>
                </div>
            </form>

And here is my snippet so far:

object PackageSearch {

  def populateTableWithPackageData(packagenumber:String) = SHtml.memoize {
    val packageData = Vector(
      Vector("48", "x0", "x1", "x2", "x3", "x4", "x5"),
      Vector("49", "y0", "y1", "y2", "y3", "y4", "y5")
    )
    "#result" #> Text(packagenumber) &
      "tbody tr *" #> packageData.map { v => {
        "td *" #> v
      }
      }
  }

  def search(in: NodeSeq): NodeSeq = {

    var packagenumber = ""
    var initialPackageData = Vector(
      Vector("", "", "", "", "", "", "")
    )

    val cssSel =
      "@packagenumber" #> text(packagenumber, packagenumber = _) &
       "div" #> populateTableWithPackageData(packagenumber) &
        "type=submit [onclick]" #> SHtml.ajaxInvoke( () =>
          SetHtml("div", populateTableWithPackageData(packagenumber).applyAgain)
        )

    cssSel(in)

  }

}

I would like the page to first load with the table populated with data from the variable initialPackageData. Then, after the user submits a package number, I would like the table to be populated with data from the variable packageData (later I will replace this with a query to the database that uses packagenumber as a search parameter). I can't get this to work though. This snippet instead simply populates the data with data from the variable packageData on the page load, then does nothing on subsequent submits.

Can someone suggest how to I can get this working? 

Many thanks,

Matt Farmer

unread,
May 13, 2015, 11:32:44 AM5/13/15
to Lift
Hey Shafique,

The first thing I see is that you appear to be using SHtml.memoize which probably isn’t what you want? I also see a few things happening in here (like a direct SetHtml) that aren’t necessary…

How about this, can you create a basic project on GitHub with this basic skeleton? Then I can go into it and make it work and hopefully explain exactly what is going wrong in detail? Might be faster than going back and forth with code in emails. My in-brain Scala compiler is worse than the computerized one. ;)


Matt Farmer Blog | Twitter

--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shafique Jamal

unread,
May 13, 2015, 9:09:46 PM5/13/15
to lif...@googlegroups.com
Dear Matt,

Thank you for responding and offering further help. I ended up getting
help from a Lift expert outside this forum to solve my this issue. I
am presenting below the solution, along with my understanding of how
it works, so that others can benefit.

The final HTML:

<form data-lift="form.ajax">
<div data-lift="PackageSearch.search">
<div id="memoizethis">
<input type="text" name="packagenumber"
placeholder="package number"/>
<input type="submit">

<div id="result">Your package number number will
be echoed here.</div>

<table class="table table-bordered table-hover
table-striped">
<thead>
<tr>
<th>Package Number</th>
<th>Package Owner</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</div>

The final code snippet:

object PackageSearch {

def populateTableWithPackageData = {

var packagenumber = ""
SHtml.idMemoize(body => {

val PackageData = Vector(
Vector("package48", "Alice"),
Vector("package49", "Bob")
)
"@packagenumber" #> text(packagenumber, s => packagenumber = s)
& // first arg is value that will in the html when
// the page first loads, and in subsequent reloads. Second arg
is a function, "will get some value and assign
// that value to the packagenumber variable. The function
represents what will happen when the form
// is submitted.
"type=submit" #> SHtml.ajaxOnSubmit(() => body.setHtml()) & //
redraws part of page that is
// contained in the #memoize div (because of the code in def
search below). The parts of the page
// outside of #memoize are not in the body variable.
"#result *" #> Text(packagenumber) &
"tbody tr *" #> PackageData.map { v => {
"td *" #> v
}
}
})
}

def search(in: NodeSeq): NodeSeq = {
val cssSel = "#memoizethis" #> populateTableWithPackageData
cssSel(in)
}

}

My understanding of this is as follows:

Using SHtml.idMemoize 'memoizes the contents of the div with id
#memoizethis' (because of this line: val cssSel = "#memoizethis" #>
populateTableWithPackageData). The 'body' variable thus contains the
html of the div tag and its contents, as well as the methods necessary
to redraw this html. When the page first loads, and on subsequent
submissions, the table is populated with the contents of the
PackageData variable. What is handy is that the ponumber variable
receives the text from the ponumber input field in the html form each
time the page is submitted, and so this can be used in a database
query to deliver different values to the PacakgeData variable and thus
the table within the #memoizethis element.
> You received this message because you are subscribed to a topic in the
> Google Groups "Lift" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/liftweb/in8prxaZIgU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
Reply all
Reply to author
Forward
0 new messages