我目前正在编写自己的Component基类,其中包含一大堆辅助方法,用于使用Twitter Bootstrap CSS框架(并避免使用它周围的所有样板代码)。它们可以像现有的表单助手一样使用(例如html div ...
)。
例如,水平文本字段(水平格式)的内容如下所示:
horizontalTextField: aLabel
| field |
field := WATextInputTag new
class: 'input-xlarge';
yourself.
self html div
class: 'control-group';
with: [
self html label
class: 'control-label';
with: aLabel.
self html div
class: 'controls';
with: [self html brush: field].
].
^ field.
在渲染组件时,我的目标是这样使用:
(self horizontalTextField: 'Titel')
on: #title of: self article;
id: 'title'.
因此,目标是将实际文本字段包装在几个div中,但仍然能够在辅助函数之外对这个包装元素进行更改(使用普通标记帮助程序访问器),如上所示。
然而,这个不起作用,因为with:
方法导致包装div在我返回元素之前被序列化(也称为渲染),然后我再也无法编辑了。
可能的解决方案:
self horizontalTextField: 'Titel' with: [:field | id: 'title']
之类的操作。然后在渲染辅助方法中的实际文本字段之前应用该块。这将非常灵活,但不是很漂亮(语法方面)。self html html: '<label class="control-label">
等。在某种程度上相当黑客,而不是非常面向对象。评论?想法?更好的建议?
答案 0 :(得分:2)
正如您所注意到的,上面的代码不起作用,因为HTML Canvas立即发出HTML。刷子不应存放在任何地方,它们只能在很短的时间内存放。 HTML画布也是如此,它非常罕见,并且可能导致错误将其存储在某处。
在Seaside中执行此操作的典型方法是创建辅助方法:
renderHorizontalLabel: aLabelRenderer andField: aFieldRenderer on: html
html div
class: 'control-group';
with: [
html label
class: 'control-label';
with: aLabelRenderable.
html div
class: 'controls';
with: aFieldRenderer ]
上述代码的优点是aLabelRenderer
和aFieldRenderer
都可以是实现#renderOn:
的任何对象(String,Number,Block,WAPresenter,WAComponent,...)。
renderContentOn: html
self
renderHorizontalLabel: 'Comment'
andField: [
html textField
value: comment;
callback: [ :value | comment := value ] ]
on: html.
self
renderHorizontalLabel: 'Acknowledge'
andField: [ self renderCheckbox: false on: html ]
on: html.
...
要生成实际字段,您可以创建其他方法,然后从您传入的块中调用aFieldRenderer
。这使您可以灵活地任意组合不同的部件。看看Seaside中的例子,有很多这种模式的用户。
答案 1 :(得分:0)
看起来你想像Tag Brush一样使用它,所以我想你肯定想要使用扩展的WACanvasTag方法 - 但只有当你真的想要在horizontalTextField情况下创建一个复合“tag”时
对于其他Bootstrap概念 - 如行,容器等,最好的办法是简单地向WAHtmlCanvas添加扩展方法。
我自己也做过 - 这是我对Bootstrap NavBar标签的实现:
WABrush subclass: #BSNavBar
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Bootstrap'
BSNavBar>>with: aBlock
super with: [
canvas div class: 'navbar'; with: [
canvas div class: 'navbar-inner'; with: [
canvas container: aBlock]]].
closed := true
以下是我实施“行”的方法 -
WAHtmlCanvas>>row
^self
div class: 'row'
WAHtmlCanvas>>row: aBlock
self row with: aBlock
此外,我还为WATagBrush添加了扩展方法,以支持span,offset和pull-right以及流体容器:
WATagBrush>>offset: anInteger
self class: 'offset', anInteger asString
WATagBrush>>beFluid
self attributeAt: #class
put: (((self attributeAt: #class ifAbsent: [^self])
copyReplaceTokens: 'container' with: 'container-fluid')
copyReplaceTokens: 'row' with: 'row-fluid')
最后,这是一个使用上述内容的示例渲染方法:
renderContentOn: html
html navBar: [
html div pullRight; with: [
self session isLoggedIn
ifTrue: [self renderUserMenuOn: html]
ifFalse: [self renderLoginBoxOn: html]]]