Repository: freemarker
Updated Branches:
  refs/heads/3 976ce3ac1 -> c4f96d918


FREEMARKER-55: Adding options directive, TODO: check option selected, support 
nested option directive.


Project: http://git-wip-us.apache.org/repos/asf/freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/freemarker/commit/c4f96d91
Tree: http://git-wip-us.apache.org/repos/asf/freemarker/tree/c4f96d91
Diff: http://git-wip-us.apache.org/repos/asf/freemarker/diff/c4f96d91

Branch: refs/heads/3
Commit: c4f96d918c388b90e115447bd21dd4185cb19fd7
Parents: 976ce3a
Author: Woonsan Ko <[email protected]>
Authored: Fri Apr 20 23:02:23 2018 -0400
Committer: Woonsan Ko <[email protected]>
Committed: Fri Apr 20 23:02:23 2018 -0400

----------------------------------------------------------------------
 .../AbstractFormTemplateDirectiveModel.java     |   8 +
 .../spring/model/form/FormTemplateScope.java    |  68 ++++++++
 .../form/OptionsTemplateDirectiveModel.java     | 160 +++++++++++++++++++
 .../form/SelectTemplateDirectiveModel.java      |  13 +-
 .../SpringFormTemplateCallableHashModel.java    |   1 +
 .../example/mvc/users/UserController.java       |  15 ++
 .../form/SelectTemplateDirectiveModelTest.java  |  26 ++-
 .../model/form/select-directive-usages.f3ah     |  33 +++-
 8 files changed, 314 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
index 00c9f42..83f078e 100644
--- 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
+++ 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
@@ -25,6 +25,7 @@ import java.io.IOException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.freemarker.core.CustomStateKey;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.spring.model.AbstractSpringTemplateDirectiveModel;
 import org.springframework.util.ObjectUtils;
@@ -34,6 +35,13 @@ import org.springframework.util.ObjectUtils;
  */
 abstract class AbstractFormTemplateDirectiveModel extends 
AbstractSpringTemplateDirectiveModel {
 
+    protected static final CustomStateKey<FormTemplateScope> 
FORM_TEMPLATE_SCOPE_KEY = new CustomStateKey<FormTemplateScope>() {
+        @Override
+        protected FormTemplateScope create() {
+            return new FormTemplateScope();
+        }
+    };
+
     protected AbstractFormTemplateDirectiveModel(HttpServletRequest request, 
HttpServletResponse response) {
         super(request, response);
     }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/FormTemplateScope.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/FormTemplateScope.java
 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/FormTemplateScope.java
new file mode 100644
index 0000000..822eb00
--- /dev/null
+++ 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/FormTemplateScope.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.spring.model.form;
+
+/**
+ * Form related <code>TemplateCallableModel</code> execution context.
+ */
+public class FormTemplateScope {
+
+    /**
+     * The <code>TagOutputter</code> instance in the current 
<code>TemplateCallableModel</code> execution context.
+     */
+    private TagOutputter currentTagOutputter;
+
+    /**
+     * The <code>SelectTemplateDirectiveModel</code> instance in the current 
<code>TemplateCallableModel</code> execution context.
+     */
+    private SelectTemplateDirectiveModel currentSelectDirective;
+
+    /**
+     * Return the <code>TagOutputter</code> instance in the current 
<code>TemplateCallableModel</code> execution context.
+     * @return the <code>TagOutputter</code> instance in the current 
<code>TemplateCallableModel</code> execution context
+     */
+    public TagOutputter getCurrentTagOutputter() {
+        return currentTagOutputter;
+    }
+
+    /**
+     * Set the <code>TagOutputter</code> instance in the current 
<code>TemplateCallableModel</code> execution context.
+     * @param currentTagOutputter the <code>TagOutputter</code> instance in 
the current <code>TemplateCallableModel</code> execution context
+     */
+    public void setCurrentTagOutputter(TagOutputter currentTagOutputter) {
+        this.currentTagOutputter = currentTagOutputter;
+    }
+
+    /**
+     * Return the <code>SelectTemplateDirectiveModel</code> instance in the 
current <code>TemplateCallableModel</code> execution context.
+     * @return the <code>SelectTemplateDirectiveModel</code> instance in the 
current <code>TemplateCallableModel</code> execution context
+     */
+    public SelectTemplateDirectiveModel getCurrentSelectDirective() {
+        return currentSelectDirective;
+    }
+
+    /**
+     * Set the <code>SelectTemplateDirectiveModel</code> instance in the 
current <code>TemplateCallableModel</code> execution context.
+     * @param currentSelectDirective the 
<code>SelectTemplateDirectiveModel</code> instance in the current 
<code>TemplateCallableModel</code> execution context
+     */
+    public void setCurrentSelectDirective(SelectTemplateDirectiveModel 
currentSelectDirective) {
+        this.currentSelectDirective = currentSelectDirective;
+    }
+}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/OptionsTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/OptionsTemplateDirectiveModel.java
 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/OptionsTemplateDirectiveModel.java
new file mode 100644
index 0000000..4367eaf
--- /dev/null
+++ 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/OptionsTemplateDirectiveModel.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.spring.model.form;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.freemarker.core.CallPlace;
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.model.ArgumentArrayLayout;
+import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.StringToIndexMap;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.servlet.support.RequestContext;
+
+/**
+ * Provides a convenient <code>TemplateModel</code> that allow to supply a 
collection that are to be rendered
+ * as HTML '{@code option}' elements.
+ * <P>
+ * This directive supports the following parameters:
+ * <UL>
+ * <LI><code>items</code>: collection of option items.</LI>
+ * <LI>
+ *   ... TODO ...
+ * </LI>
+ * </UL>
+ * </P>
+ * <P>
+ * Some valid example(s):
+ * </P>
+ * <PRE>
+ *   ...
+ * </PRE>
+ * <P>
+ * <EM>Note:</EM> Unlike Spring Framework's <code>&lt;form:input /&gt;</code> 
JSP Tag Library, this directive
+ * does not support <code>htmlEscape</code> parameter. It always renders 
HTML's without escaping
+ * because it is much easier to control escaping in FreeMarker Template 
expressions.
+ * </P>
+ */
+class OptionsTemplateDirectiveModel extends 
AbstractHtmlInputElementTemplateDirectiveModel {
+
+    public static final String NAME = "options";
+
+    private static final int NAMED_ARGS_OFFSET = 
AbstractHtmlInputElementTemplateDirectiveModel.ARGS_LAYOUT
+            .getPredefinedNamedArgumentsEndIndex();
+
+    private static final int ITEMS_PARAM_IDX = NAMED_ARGS_OFFSET;
+    private static final String ITEMS_PARAM_NAME = "items";
+
+    private static final int ITEM_VALUE_PARAM_IDX = NAMED_ARGS_OFFSET + 1;
+    private static final String ITEM_VALUE_PARAM_NAME = "itemValue";
+
+    private static final int ITEM_LABEL_PARAM_IDX = NAMED_ARGS_OFFSET + 2;
+    private static final String ITEM_LABEL_PARAM_NAME = "itemLabel";
+
+    protected static final ArgumentArrayLayout ARGS_LAYOUT = 
ArgumentArrayLayout.create(1, false,
+            StringToIndexMap.of(
+                    
AbstractHtmlInputElementTemplateDirectiveModel.ARGS_LAYOUT.getPredefinedNamedArgumentsMap(),
+                    new StringToIndexMap.Entry(ITEMS_PARAM_NAME, 
ITEMS_PARAM_IDX),
+                    new StringToIndexMap.Entry(ITEM_VALUE_PARAM_NAME, 
ITEM_VALUE_PARAM_IDX),
+                    new StringToIndexMap.Entry(ITEM_LABEL_PARAM_NAME, 
ITEM_LABEL_PARAM_IDX)),
+            true);
+
+    private TemplateModel items;
+    private String itemValue;
+    private String itemLabel;
+
+    protected OptionsTemplateDirectiveModel(HttpServletRequest request, 
HttpServletResponse response) {
+        super(request, response);
+    }
+
+    @Override
+    public boolean isNestedContentSupported() {
+        return false;
+    }
+
+    @Override
+    public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
+        return ARGS_LAYOUT;
+    }
+
+    @Override
+    protected void executeInternal(TemplateModel[] args, CallPlace callPlace, 
Writer out, final Environment env,
+            ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, 
RequestContext requestContext)
+            throws TemplateException, IOException {
+
+        super.executeInternal(args, callPlace, out, env, 
objectWrapperAndUnwrapper, requestContext);
+
+        items = CallableUtils.getOptionalArgument(args, ITEMS_PARAM_IDX, 
TemplateModel.class, this);
+        itemValue = CallableUtils.getOptionalStringArgument(args, 
ITEM_VALUE_PARAM_IDX, this);
+        itemLabel = CallableUtils.getOptionalStringArgument(args, 
ITEM_LABEL_PARAM_IDX, this);
+
+        final FormTemplateScope formTemplateScope = 
env.getCustomState(FORM_TEMPLATE_SCOPE_KEY);
+        final SelectTemplateDirectiveModel curSelectDirective = 
formTemplateScope.getCurrentSelectDirective();
+
+        Object optionItems = null;
+
+        if (getItems() != null) {
+            optionItems = objectWrapperAndUnwrapper.unwrap(getItems());
+            if (optionItems != null) {
+                optionItems = evaluate("items", optionItems);
+            }
+        }
+
+        if (optionItems != null) {
+            final String selectName = curSelectDirective.getName();
+            final String valueProperty = (getItemValue() != null
+                    ? ObjectUtils.getDisplayString(evaluate("itemValue", 
getItemValue()))
+                    : null);
+            final String labelProperty = (getItemLabel() != null
+                    ? ObjectUtils.getDisplayString(evaluate("itemLabel", 
getItemLabel()))
+                    : null);
+            OptionOutputHelper optionOutHelper = new 
OptionOutputHelper(optionItems, curSelectDirective.getBindStatus(),
+                    valueProperty, labelProperty) {
+                @Override
+                protected String processOptionValue(String resolvedValue) 
throws TemplateException {
+                    return processFieldValue(env, selectName, resolvedValue, 
"option");
+                }
+            };
+
+            
optionOutHelper.writeOptions(formTemplateScope.getCurrentTagOutputter());
+        }
+    }
+
+    public TemplateModel getItems() {
+        return items;
+    }
+
+    public String getItemValue() {
+        return itemValue;
+    }
+
+    public String getItemLabel() {
+        return itemLabel;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModel.java
 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModel.java
index 26a170c..c405437 100644
--- 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModel.java
+++ 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModel.java
@@ -109,8 +109,7 @@ class SelectTemplateDirectiveModel extends 
AbstractHtmlInputElementTemplateDirec
 
     @Override
     public boolean isNestedContentSupported() {
-        // TODO: should return true for options and option directive? What if 
there's anything other than option(s)?
-        return false;
+        return true;
     }
 
     @Override
@@ -169,6 +168,16 @@ class SelectTemplateDirectiveModel extends 
AbstractHtmlInputElementTemplateDirec
             optionOutHelper.writeOptions(tagOut);
         }
 
+        final FormTemplateScope formTemplateScope = 
env.getCustomState(FORM_TEMPLATE_SCOPE_KEY);
+        try {
+            formTemplateScope.setCurrentTagOutputter(tagOut);
+            formTemplateScope.setCurrentSelectDirective(this);
+            callPlace.executeNestedContent(null, out, env);
+        } finally {
+            formTemplateScope.setCurrentSelectDirective(null);
+            formTemplateScope.setCurrentTagOutputter(null);
+        }
+
         tagOut.endTag();
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SpringFormTemplateCallableHashModel.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SpringFormTemplateCallableHashModel.java
 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SpringFormTemplateCallableHashModel.java
index 7d29c28..31e1591 100644
--- 
a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SpringFormTemplateCallableHashModel.java
+++ 
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/SpringFormTemplateCallableHashModel.java
@@ -53,6 +53,7 @@ public final class SpringFormTemplateCallableHashModel 
implements TemplateHashMo
         modelsMap.put(ButtonTemplateDirectiveModel.NAME, new 
ButtonTemplateDirectiveModel(request, response));
         modelsMap.put(LabelTemplateDirectiveModel.NAME, new 
LabelTemplateDirectiveModel(request, response));
         modelsMap.put(SelectTemplateDirectiveModel.NAME, new 
SelectTemplateDirectiveModel(request, response));
+        modelsMap.put(OptionsTemplateDirectiveModel.NAME, new 
OptionsTemplateDirectiveModel(request, response));
         modelsMap.put(ErrorsTemplateDirectiveModel.NAME, new 
ErrorsTemplateDirectiveModel(request, response));
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
 
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
index 77fa2a9..71ba8e0 100644
--- 
a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
+++ 
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
@@ -20,6 +20,9 @@
 package org.apache.freemarker.spring.example.mvc.users;
 
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -43,6 +46,15 @@ import org.springframework.web.bind.annotation.RequestParam;
 @Controller
 public class UserController {
 
+    public static final List<String> INDOOR_SPORTS = Collections
+            .unmodifiableList(Arrays.asList("bowling", "gymnastics", 
"handball"));
+
+    public static final List<String> OUTDOOR_SPORTS = Collections
+            .unmodifiableList(Arrays.asList("baseball", "football", 
"marathon"));
+
+    public static final List<String> ALL_SPORTS = Collections
+            .unmodifiableList(Arrays.asList("bowling", "gymnastics", 
"handball", "baseball", "football", "marathon"));
+
     private static final String DEFAULT_USER_LIST_VIEW_NAME = 
"example/users/userlist";
 
     private static final String DEFAULT_USER_EDIT_VIEW_NAME = 
"example/users/useredit";
@@ -72,6 +84,9 @@ public class UserController {
     @RequestMapping(value = "/users/{id:\\d+}", method = RequestMethod.GET)
     public String getUser(@PathVariable("id") Long id,
             @RequestParam(value = "viewName", required = false) String 
viewName, Model model) {
+        model.addAttribute("indoorSports", INDOOR_SPORTS);
+        model.addAttribute("outdoorSports", OUTDOOR_SPORTS);
+
         User user = userRepository.getUser(id);
 
         if (user != null) {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModelTest.java
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModelTest.java
 
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModelTest.java
index 4a82c67..c07fb8d 100644
--- 
a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModelTest.java
+++ 
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/form/SelectTemplateDirectiveModelTest.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.spring.model.form;
 
 import org.apache.freemarker.spring.example.mvc.users.User;
+import org.apache.freemarker.spring.example.mvc.users.UserController;
 import org.apache.freemarker.spring.example.mvc.users.UserRepository;
 import org.junit.Before;
 import org.junit.Test;
@@ -30,6 +31,7 @@ import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
 
@@ -61,12 +63,24 @@ public class SelectTemplateDirectiveModelTest {
     public void testBasicUsages() throws Exception {
         final Long userId = userRepository.getUserIds().iterator().next();
         final User user = userRepository.getUser(userId);
-        mockMvc.perform(get("/users/{userId}/", userId).param("viewName", 
"test/model/form/select-directive-usages")
+        final ResultActions resultAcctions =
+                mockMvc.perform(get("/users/{userId}/", 
userId).param("viewName", "test/model/form/select-directive-usages")
                 
.accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())
-                
.andExpect(content().contentTypeCompatibleWith("text/html")).andDo(print())
-                
.andExpect(xpath("//form[@id='form1']//select[@name='favoriteSport']//option[@value='football']").exists())
-                
.andExpect(xpath("//form[@id='form1']//select[@name='favoriteSport']//option[@value='handball']").exists())
-                
.andExpect(xpath("//form[@id='form1']//select[@name='favoriteSport']//option[@value='basketball']").exists())
-                
.andExpect(xpath("//form[@id='form1']//select[@name='favoriteSport']//option[@value='volleyball']").exists());
+                
.andExpect(content().contentTypeCompatibleWith("text/html")).andDo(print());
+
+        for (int i = 0; i < UserController.INDOOR_SPORTS.size(); i++) {
+            String sport = UserController.INDOOR_SPORTS.get(i);
+            
resultAcctions.andExpect(xpath("//form[@id='form1']//select[@name='favoriteSport']//option["
 + (i + 1) + "]").string(sport));
+        }
+
+        for (int i = 0; i < UserController.OUTDOOR_SPORTS.size(); i++) {
+            String sport = UserController.OUTDOOR_SPORTS.get(i);
+            
resultAcctions.andExpect(xpath("//form[@id='form2']//select[@name='favoriteSport']//option["
 + (i + 1) + "]").string(sport));
+        }
+
+        for (int i = 0; i < UserController.ALL_SPORTS.size(); i++) {
+            String sport = UserController.ALL_SPORTS.get(i);
+            
resultAcctions.andExpect(xpath("//form[@id='form3']//select[@name='favoriteSport']//option["
 + (i + 1) + "]").string(sport));
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/c4f96d91/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/select-directive-usages.f3ah
----------------------------------------------------------------------
diff --git 
a/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/select-directive-usages.f3ah
 
b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/select-directive-usages.f3ah
index 7152055..0794c2c 100644
--- 
a/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/select-directive-usages.f3ah
+++ 
b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/select-directive-usages.f3ah
@@ -26,8 +26,37 @@
       <tr>
         <th>Favorite Sport:</th>
         <td>
-          <#assign sports=[ 'football', 'handball', 'basketball', 'volleyball' 
] />
-          <@form.select 'user.favoriteSport' items=sports />
+          <@form.select 'user.favoriteSport' items=indoorSports />
+        </td>
+      </tr>
+    </table>
+  </form>
+
+  <h1>Form 2</h1>
+  <hr/>
+  <form id="form2">
+    <table>
+      <tr>
+        <th>Favorite Sport:</th>
+        <td>
+          <@form.select 'user.favoriteSport'>
+            <@form.options items=outdoorSports />
+          </@form.select>
+        </td>
+      </tr>
+    </table>
+  </form>
+
+  <h1>Form 3</h1>
+  <hr/>
+  <form id="form3">
+    <table>
+      <tr>
+        <th>Favorite Sport:</th>
+        <td>
+          <@form.select 'user.favoriteSport' items=indoorSports>
+            <@form.options items=outdoorSports />
+          </@form.select>
         </td>
       </tr>
     </table>

Reply via email to