Re: [Lift] TableEditor usage example (beginners question)

156 views
Skip to first unread message

Naftoli Gugenheim

unread,
Oct 28, 2012, 7:21:19 PM10/28/12
to lif...@googlegroups.com
Can you show your code?


On Fri, Oct 26, 2012 at 8:16 AM, Anke Herrmann <herrma...@gmail.com> wrote:
Hello, I'm new to Lift (and Scala for that matter) and trying to build my first app. For lookup tables (categories etc.) I'd like to use TableEditor. Following the instructions I register the table in boot and call the snippet from my template. 
The table title shows correctly, the rest of the page is blank. Looking at the source I see the Table editor default template markup unchanged so I assume I've not registered the table correctly in boot.scala and the snippet is never called.
Can anyone point me to an example for using TableEditor? Any help is much appreciated. Thanks

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

Anke Herrmann

unread,
Oct 30, 2012, 10:18:55 AM10/30/12
to lif...@googlegroups.com
Hello. Thanks a lot for your reply.
 
I've got a simple mapper model ExpenseCategory:
trait Lookup[L <: Lookup[L]] extends LongKeyedMapper[L] {
     
self: L =>
     
object name extends MappedString[L](this, 100) {
       
override def validations =
          valMinLen
(3, "Lookup name must be at least 3 characters") _ ::
          valUnique
("Lookup name must be unique") _ ::
         
super.validations
     
}
}
//ExpenseCategory
class ExpenseCategory extends Lookup[ExpenseCategory] with IdPK {
   
def getSingleton = ExpenseCategory
   
def canDelete = true
}
object ExpenseCategory extends ExpenseCategory with LongKeyedMetaMapper[ExpenseCategory]{
   
override def dbTableName = "expense_categories"
}
 
Then in boot.scala just after Schemifier:
 
TableEditor.registerTable("cats", ExpenseCategory, "Expense Categories")


And the template:
 
<div id="main" class="lift:surround?with=default;at=content">
       
<h2>Lookups</h2>
       
<div class="lift:TableEditor.edit?table=cats;eager_eval=true">
           
<span class="lift:embed?what=/tableeditor/default"></span>
       
</div>
 
</div>

I remember reading somewhere (I think it was you, Naftoli, replying to a comment in a TableEditor thread) that setting up TableEditor requires 2 lines of code in boot.scala and 3 in the template so I assume it is in boot.scala that I'm missing something.
Thanks for your help.

Naftoli Gugenheim

unread,
Oct 30, 2012, 10:20:24 PM10/30/12
to lif...@googlegroups.com
Not sure why it's not working. If you like you can post a self-contained project that demonstrates the issue and I can look at it.

You can also try the following:
  1. Skip the registerTable call
  2. Change TableEditor.edit to the name of a new snippet you'll write, e.g. MyTableEditor:
import net.liftweb.mapper.view.{ ItemsList, ItemsListEditor }
class MyTableEditor {
  def render = (new ItemsListEditor[T] {
     var items = new ItemsList[T] {
       val metaMapper = S.attr("table").map {
         case "cat" => ExpenseCategory
       }.openOr(sys.error("No table attribute"))
  }).edit _
}

That's essentially what TableEditor does, except that registerTable caches the ItemsListEditor instance.
If it still doesn't work, you will be better positioned to debug it, since you will be dealing with your own instance. For instance you could override ItemsListEditor.edit, print out the input NodeSeq, then val ret = super.edit(ns), print out ret, and return it.

Anke Herrmann

unread,
Nov 1, 2012, 8:15:10 AM11/1/12
to lif...@googlegroups.com
Thanks a lot for your reply. I really appreciate your help.
I tried to write the snippet you suggested but IntelliJ complained "type not found: T" and so, being a total Scala newbie, I couldn't get it to compile but I'll have another go at it. The issue isn't important enough to post an example project and waste your time looking at it, especially since I managed to implement the functionality I'm after using idMemoize.

Naftoli Gugenheim

unread,
Nov 1, 2012, 6:03:34 PM11/1/12
to lif...@googlegroups.com
Sorry about that. Try this one:

import net.liftweb.mapper.view.{ ItemsList, ItemsListEditor }
class ExpenseCategoryEditor {
  def /* or val if you prefer */ editor = new ItemsListEditor[ExpenseCategory] {
    val items = new ItemsList[ExpenseCategory] {
      val metaMapper = ExpenseCategory
    }
  }
  def render = editor.edit _
}

<div id="main" class="lift:surround?with=default;at=content">
        
<h2>Lookups</h2>

        
<div class="lift:ExpenseCategoryEditor?eager_eval=true">

            
<span class="lift:embed?what=/tableeditor/default"></span>
        
</div>
 
</div>

Naftoli Gugenheim

unread,
Nov 1, 2012, 6:05:32 PM11/1/12
to lif...@googlegroups.com
Or better yet,

class ExpenseCategoryEditor extends ItemsListEditor[ExpenseCategory] {
  val items = new ItemsList[ExpenseCategory] {
    val metaMapper = ExpenseCategory
  }
}

<div class="lift:ExpenseCategoryEditor.edit?eager_eval=true">

David Pollak

unread,
Dec 6, 2012, 1:47:03 PM12/6/12
to lif...@googlegroups.com


On Thu, Dec 6, 2012 at 5:14 AM, Stepan Grigorovich <sgrigo...@fanwave.com> wrote:
I have same problems.

In ItemsListEditor
"saveBtn" -> SHtml.submit(?("Save"), onSubmit _, noPrompt)

but in /tableeditor/default

</table>
<table:saveBtn />
</lift:children>


If you're using Html5 (basically any Lift started template created in the last few years), <table:saveBtn/> is invalid. You must write <table:saveBtn></table:saveBtn> But please, please, please use the CSS Selector Transforms. They are so much better than bind()
 
It's bug?


On Friday, 26 October 2012 18:16:40 UTC+6, Anke Herrmann wrote:
Hello, I'm new to Lift (and Scala for that matter) and trying to build my first app. For lookup tables (categories etc.) I'd like to use TableEditor. Following the instructions I register the table in boot and call the snippet from my template. 
The table title shows correctly, the rest of the page is blank. Looking at the source I see the Table editor default template markup unchanged so I assume I've not registered the table correctly in boot.scala and the snippet is never called.
Can anyone point me to an example for using TableEditor? Any help is much appreciated. Thanks

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



--
Telegram, Simply Beautiful CMS https://telegr.am
Lift, the simply functional web framework http://liftweb.net


Stepan Grigorovich

unread,
Dec 6, 2012, 10:49:18 PM12/6/12
to lif...@googlegroups.com
Thanks for the answer, but I am using the standard template.
Few details:
In lift-mapper_2.9.1-2.5-M3.jar TableEditor
).bind("table",
         "title" -> title,
         "insertBtn" -> SHtml.submit(?("Insert"), onInsert _, noPrompt),
         "items" -> {ns:NodeSeq =>
           items.items.flatMap {i =>
             bind("item",
                  customBind(i)(ns),
                  "fields" -> eachField(
                    i,
                    (f: MappedField[_,T]) => Seq("form" -> f.toForm),
                    fieldFilter
                  ),
                  "removeBtn" -> SHtml.submit(?("Remove"), ()=>onRemove(i), noPrompt),
                  "msg" -> ((i.validate match {
                    case Nil =>
                      if(!i.saved_?) Text(?("New")) else if(i.dirty_?) Text(?("Unsaved")) else NodeSeq.Empty
                    case errors => (<ul>{errors.flatMap(e => <li>{e.msg}</li>)}</ul>)
                  }))
             )
           } ++ items.removed.flatMap { i =>
             bind("item", customBind(i)(ns),
                  "fields" -> eachField(
                    i,
                    {f: MappedField[_,T] => Seq("form" -> <strike>{f.asHtml}</strike>)},
                    fieldFilter
                  ),
                  "removeBtn" -> NodeSeq.Empty,
                  "msg" -> Text(?("Deleted"))
             )
           }: NodeSeq
         },
         "saveBtn" -> SHtml.submit(?("Save"), onSubmit _, noPrompt)
    )
In lift-mapper_2.9.1-2.5-M3.jar /tableeditor/default.html
<lift:children>
<head>
<title><table:title /></title>
</head>
<h3><table:title /></h3>
<table>
<thead>
<tr>
<header:fields>
<th><field:name /></th>
</header:fields>
<td><table:insertBtn /></td>
<td></td>
</tr>
<tr>
<td colspan="5">
<hr />
</td>
</tr>
</thead>
<tbody>
<table:items>
<tr>
<item:fields>
<td style="vertical-align: top"><field:form /></td>
</item:fields>
<td style="vertical-align: top"><item:removeBtn /></td>
<td><item:msg /></td>
</tr>
<tr>
<td colspan="5">
<hr />
</td>
</tr>
</table:items>
</tbody>
</table>
<table:saveBtn />
</lift:children>


But in out html 

<title>&lt;table:title /&gt;</title>
<h3>Cats</h3>
<item:fields>
</item:fields><table>
<thead>
<tr>
<th><field:name></field:name></th>
<td><table:insertbtn></table:insertbtn></td>
<td></td>
</tr>
<tr>
<td colspan="5">
<hr>
</td>
</tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: top"><field:form></field:form></td>
<td style="vertical-align: top"><item:removebtn></item:removebtn></td>
<td><item:msg></item:msg></td>
</tr>
<tr>
<td colspan="5">
<hr>
</td>
</tr>
</tbody>
</table>
<table:savebtn>

Tags have differ. Because of the difference does not insert data

David Pollak

unread,
Dec 7, 2012, 12:22:11 PM12/7/12
to lif...@googlegroups.com
Please use the CSS Selector Transforms, not bind().

If you continue to have problems, please put together example code (see https://www.assembla.com/wiki/show/liftweb/Posting_example_code ) and we'll take a look at it.

Stepan Grigorovich

unread,
Dec 10, 2012, 4:26:05 AM12/10/12
to lif...@googlegroups.com
Sorry for my english.

As I understand TableEditor not work with html5. And snipet in link invalid, simple project with an example github.

Naftoli Gugenheim

unread,
Dec 12, 2012, 3:15:25 AM12/12/12
to liftweb
No, what DPP said is that you have to close the tag manually. You can't write a custom null tag ( <x:y /> ). Instead use <x:y></x:y>.

I apologize for not being able to take a look at the github project at the moment --- I'm a bit out of commission. I'll try to respond to questions though.
Reply all
Reply to author
Forward
0 new messages