I am trying to use custom tag with variables.
for eg)
<c:forEach var="test" items="itemstest">
${test}
</c:forEach>
In the above code i am able to access the test value inside the <c:forEach> tag.
I need to create a custom tag with similar functionality.
I have got info from the oracle docs http://docs.oracle.com/javaee/5/tutorial/doc/bnamu.html under title Declaring Tag Variables for Tag Handlers.
Can anyone pls help me to implement the same with example.
Hi i have solved it in the following way
class: test.java
public void doTag() throws JspException, IOException {
getJspContext().getOut().flush();
//any method or operation
super.doTag();
getJspContext().setAttribute(variable, "Hello");
}
Create getter setter for variable
tld file:
<tag>
<name>test</name>
<tag-class>com.org.test</tag-class>
<body-content>empty</body-content>
<attribute>
<name>inputValue</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>variable</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
jsp file:
<%# taglib uri="/WEB-INF/tld/tldfilename.tld" prefix="tag" %>
<tag:test inputValue="hello" variable="testValue"/>
${testValue}
For something so simple, you may be better off using tag files, which makes it easy to create a tag library using some small additions to the normal jsp syntax (and is part of the standard)
http://docs.oracle.com/javaee/1.4/tutorial/doc/JSPTags5.html
A "tag with variables" is done using an attribute declaration, JSP code is quite simple:
<%#tag pageEncoding="utf-8" %>
<%-- dont forget to add declaration for JSTL here -->
<%#attribute name="test" type="java.lang.String" required="true" %>
<c:forEach var="test" items="itemstest">
${test}
</c:forEach>
See the linked documentation on whre to put and name the files to make them accessible within you own jsp files.
Related
I'm trying to add a single, simple client-only validation rule while using jQuery unobtrusive. My validation function is never called, the alert never fires. What am I doing wrong? I've stripped this down from a much more complex MVC application.
<html>
<head>
<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.3.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.13.1/jquery.validate.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.js"></script>
<script>
jQuery.validator.addMethod("mysplit", function () {
alert("in validator");
return false;
}, "Barf");
result = jQuery.validator.unobtrusive.adapters.addBool("mysplit");
</script>
</head>
<body>
<form method="post">
<input type="text" data-val="True", data-val-mysplit="error msg" />
<input type="submit" />
</form>
</body>
</html>
Not sure if this matters for a simple .htm file but in my web.config, everything looks correct:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="none" />
I am still unable to decorate an HTML element to make it work with unobtrusive validation. It appears that if you don't have an adaptor for your custom rule, then manually adding the unobtrusive HTML attributes will not work. However I did discover that you can decorate elements to be validated directly by jQuery.validate (more or less skipping the unobtrusive validation). I don't know if manually adding jQuery.validation data attributes this way will conflict with the validation done by unobtrusive if you have, for example, a [Required] attribute on the element that gets converted to the "data-val" attributes by unobtrusive.
In short you can add a client validation method with the usual jQuery.validator.addMethod() then trigger it with the proper data-rule attributes (not data-val, which unobtrusive uses). For example to validate that an input field has the value "hello", I can add a rule:
jQuery.validator.addMethod("hello", function (value, element, params) {
return this.optional(element) || /^hello$/.test(value);
});
Note: don't add the error message param to addMethod, it will conflict with #Html.ValidationMessageFor() if you are using that.
Then manually decorate your HTML element like:
#Html.EditorFor(model => model.sendOn, new
{
htmlAttributes = new
{
data_rule_hello="true"
}
})
Any jQuery.validate will fire.
Note that trying to use data-rule-pattern="hello" just refused to work for me so I went the addMethod() route.
In my case rather that switch totally away from unobtrusive just because I can't validate this one input is a much worse option than this bit of a hack to do my custom validation of an input element or two here or there.
This article was key to exposing the data-rule magic.
I have yet to find out if this technique causes any serious problems in production but it seems to work for me.
I would also recommend that people consider writing a custom adaptor for their own model attributes if they need custom validation instead of a one-off hack like this.
A have problem with accessing my custom components (which are used as parts of the form).
Here is the story:
I have dynamic form which have few modes of work. Each mode can be selected and loaded into form body with AJAX. It looks like that (template):
<t:form t:id = "form">
<p class= "calcModeTitle">
${message:modeLabel}: <select t:id="modeSelect"
t:type="select"
t:model="modesModel"
t:value="selectedMode"
t:blankOption="NEVER"
t:encoder="modeEncoder"
t:zone = "modeZone"
/>
</p>
<div class="horizontal_tab">
<t:errors/>
</div>
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:if test="showCompany">
<t:delegate to="block:companyBlock" />
</t:if>
<t:if test="showPersonal">
<t:delegate to="block:personalBlock" />
</t:if>
<t:if test="showMulti">
<t:delegate to="block:multiBlock" />
</t:if>
</t:zone>
<t:block id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
<div class="horizontal_tab">
<input type="submit" value="${message:submit_label}" class="submitButton thickBtn"/>
</div>
</t:form>
AJAX works pretty well and form changes accordingly the "modeSelect" state. But i run into problem when submitting the form. I have in class definition hooks for components placed as:
//----form elements
#Component(id = "form")
private Form form;
#InjectComponent
private CompanyMode company;
#InjectComponent
private PersonalMode personal;
#InjectComponent
private MultiMode multi;
where *Mode classes are my own components, containing form elements and input components. I planned to get access to them during validation, and check values supplied by user with form, but when I am trying to reach anything from them I've got nullPointerException - it seems that component are not initialized in my class definition of form. On the other hand form component is injected properly (I am able to write some error for example). I am a bit lost now. How to properly inject my components to class page containing the form?
Dynamic forms in tapestry are a bit complicated. Tapestry passes a t:formdata request parameter which contains the serialized form entities. This is then used serverside in the POST to re-hydrate initial form state. This must be kept up-to-date with what the client sees.
If you want to add dynamic content to a form via ajax, you will need to use the FormInjector. You might want to take a look at the source code for the AjaxFormLoop to see an example.
If you want to render hidden form fragments and make them visible based on clientside logic, you can use the FormFragment
From tapestry guide:
A block does not normally render; any component or contents you put
inside a block will not ordinarily be rendered. However, by injecting
the block you have precise control over when and if the content
renders.
Try to use here either "t:if" or "t:delegate".
Something like this:
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:delegate to="myBlock" />
</t:zone>
<t:block t:id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block t:id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block t:id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
java:
#Inject
private Block companyBlock, personalBlock, multiBlock;
public Block getMyBlock(){
if (getShowCompany()) return companyBlock;
if (getShowPersonal()) return personalBlock;
return multiBlock;
}
I have a problem with internationalization. I'm trying to implement support two languages in my GWT application. Unfortunately I never found a complete example how to do it with the help of UiBinder. That is what I did:
My module I18nexample.gwt.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='i18nexample'>
<inherits name="com.google.gwt.user.User" />
<inherits name='com.google.gwt.user.theme.clean.Clean' />
<inherits name="com.google.gwt.i18n.I18N" />
<inherits name="com.google.gwt.i18n.CldrLocales" />
<entry-point class='com.myexample.i18nexample.client.ExampleI18N' />
<servlet path="/start" class="com.myexample.i18nexample.server.StartServiceImpl" />
<extend-property name="locale" values="en, fr" />
<set-property-fallback name="locale" value="en" />
</module>
My interface Message.java:
package com.myexample.i18nexample.client;
import com.google.gwt.i18n.client.Constants;
public interface Message extends Constants {
String greeting();
}
The same package com.myexample.i18nexample.client has three properties file:
Message.properties:
greeting = hello
Message_en.properties:
greeting = hello
Message_fr.properties:
greeting = bonjour
My UiBinder file Greeting.ui.xml:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
ui:generateFormat="com.google.gwt.i18n.rebind.format.PropertiesFormat"
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default" >
<ui:with type="com.myexample.i18nexample.client.Message" field="string" />
<g:HTMLPanel>
<ui:msg key="greeting" description="greeting">Default greeting</ui:msg>
</g:HTMLPanel>
</ui:UiBinder>
When the application starts, I always get the output in the browser:
Default greeting
Why? What am I doing wrong?
I tried to run the application from different URL:
http://127.0.0.1:8888/i18nexample.html?gwt.codesvr=127.0.0.1:9997
http://127.0.0.1:8888/i18nexample.html?locale=en&gwt.codesvr=127.0.0.1:9997
http://127.0.0.1:8888/i18nexample.html?locale=fr&gwt.codesvr=127.0.0.1:9997
The result does not change. Although I expected in last case a message bonjour.
If for example I use a g:Buttton instead of the message ui:msg:
<g:HTMLPanel>
<g:Button text="{string.greeting}" />
</g:HTMLPanel>
Then I get as a result of the button with text "hello"
And if I enter the URL:
http://127.0.0.1:8888/i18nexample.html?locale=fr&gwt.codesvr=127.0.0.1:9997
The text on the button changes to "bonjour". Here everything works as expected. But why internationalization is not working in my first case?
And whether there is a difference between the following:
<ui:msg description="greeting">Default greeting</ui:msg>
<ui:msg description="greeting">hello</ui:msg>
<ui:msg description="greeting"></ui:msg>
Should there be different results in these cases? How to write properly?
Please explain to me the principles of internationalization in GWT and why my example does not work.
Any suggestions would be greatly appreciated.
First, the files should be named Message_fr.properties (resp. Message_en.properties), not Message.properties_fr (resp. Message.properties_en).
Then ui:msg et al. in UiBinder will generate an interface (extending com.google.gwt.i18n.client.Messages)), not use one that you defined. For that, you have to use {string.greeting} (where string is the ui:field you gave to your ui:with). The UiBinder generator will do a GWT.create() on the type class of your ui:with, which is what you'd have done in Java code:
Message string = GWT.create(Message.class);
String localizedGreeting = string.greeting();
In the implicit Messages interface (generated by UiBinder), the various ui:generateXxx attributes on the ui:UiBinder will be transformed into annotations on the interface (properties of the #Generate annotation, or the value of the #GenerateKeys annotation).
Then, one method will be generated for each ui:msg, where the attributes generate equivalent annotations (#Key, #Description) and the content of the ui:msg element is the value of the #DefaultMessage annotation. When you have or widgets inside the content, they'll be turned into arguments to the method and placeholders in the #DefaultMessage text (the values will be filled by UiBinder).
I'd suggest you make something working without UiBinder first, and understand how it works; then try the ui:msg in UiBinder, using -gen in DevMode or the compiler so you can see exactly what code does UiBinder generate (yes, it really only generates code that you could have written yourself by hand).
Also, you should add a <set-property name="locale" value="en, fr" /> or you'll still have the default locale around, despite the set-property-fallback (it'd just never be used)).
I want to put an anchor tag into a Struts2 variable that I can then display at various points in a JSP. That way I can avoid duplicating the complicated if/then statements that are used to build various forms of the href tag.
I'm using the Struts 's:set' tag to do this.
The problem is that Struts converts the '<' characters to htmlentities and when the page displays I see the actual "a href=someURL" tag displayed, not a working link.
If I add the "escape='true'" argument to s:set it does the same thing, only it displays the htmlentities for the '<' and '>' tags.
How do I put a valid anchor tag into a Struts2 variable and then display it as a working link?
Here's what I'm doing:
<s:set name="composerName">
<s:property value="'a href=%{viewRecordURL}>'" escape="false"/>
<s:property value="#composer.title" />
<s:property value="#composer.firstName" />
<s:property value="#composer.lastName" />
<s:property value="'</a>'" escape="false" />
</s:set>
Use s:url to create a valid url and then use it in s:a to generate the link.
You can refer the link below for more details:
http://struts.apache.org/2.1.8/docs/a.html
We can use url tag to create URL like mention below
<s:url id="hLink" action="yourStrutsActionName">
<s:param name="propertyName" value="%{propertyName}" />
</s:url>
<td><s:a href="%{hLink}"><s:property value="%{propertyName}"/></s:a></td>
do this easy way to set the link in Struts2
// add the Struts2 action in href
<s:a href="forgetPasswordPage.action" >Forget Password</s:a>
This isn't how you want to build this--what you have is two different things, a URL, and the text string of that url. The URL you already have. Only use <s:set> for the link text.
If you really need to, you can wrap this up into a JSP-based custom tag, but I wouldn't bother.
I'll answer my own question. Maybe someone else has a more elegant solution. Once again, we're trying to get both an anchor tag and a url into a s:set variable. The issues were two: 1) getting s:set to treat the tag string as a literal string and not an Object (which it wants to fetch from ActionContext or somewhere), and 2) turning off escaping so that the string text of the anchor tag isn't converted into htmlentities like '& lt;'.
For 1, I set the var to null, but provide a default argument, which s:property always treats as a literal string.
For #2, it's just a matter of using escape="false" in the right places.
Unfortunately, the string has to be built up with separate bits of s:property, but what can you do?
<s:set name="composerName" >
<s:property value="" default="<a href=" escape="false"/>
<s:property value="" default="'" />
<s:property value="%{viewRecordURL}" escape="true"/>
<s:property value="" default="'>" escape="false" />
<s:property value="#composer.title" />
<s:property value="#composer.firstName" />
<s:property value="#composer.lastName" />
<s:property value="" default="</a>" escape="false"/>
</s:set>
I haven't tested it yet with UTF-8 characters or potentially problematic characters like '&', apostrophe, or single quote in the #composer part.
I had the same issue, and I just solved it as following:
In the main bean, I have the following variables with Setters and Getters:
private int ReqNo;
private String hyperLinkToPage;
In the JSP page I have the TD as following:
<td class="displayValue" style="width: 10%;"><s:a href="%{hyperLinkToPage}"><s:property value="%{ReqNo}"/></s:a></td>
I hope that it will help.
Can anyone provide a dummy guide \ code snippets on how to create a front end form in Magento that posts data to a controller action.
Im trying to write a variant of the contact us from. (I know its easy to modify the contact us form, as outlined here). I'm trying to also create a feedback form with additional fields.
Given this basic form:
<form action="<?php echo $this->getFormAction(); ?>" id="feedbackForm" method="post">
<div class="input-box">
<label for="name"><?php echo Mage::helper('contacts')->__('Name') ?> <span class="required">*</span></label><br />
<input name="name" id="name" title="<?php echo Mage::helper('contacts')->__('Name') ?>" value="<?php echo $this->htmlEscape($this->helper('contacts')->getUserName()) ?>" class="required-entry input-text" type="text" />
</div>
<div class="button-set">
<p class="required"><?php echo Mage::helper('contacts')->__('* Required Fields') ?></p>
<button class="form-button" type="submit"><span><?php echo Mage::helper('contacts')->__('Submit') ?></span></button>
</div>
</form>
What are the basic step I need to take to get inputted name to a controller action for processing?
If any one is interested, I solved this by building my own module which was heavily based on the Magento_Contacts module.
Here are some links that helped me figure things out.
http://www.magentocommerce.com/wiki/custom_module_with_custom_database_table
http://inchoo.net/ecommerce/magento/magento-custom-emails/
To make $this->getFormAction() return the URL to your custom controller, you have two options:
call setFormAction() somewhere else on the block.
use a custom block type that implements getFormAction().
(1) is what happens in Mage_Contacts_IndexController::indexAction(), but (2) is the cleaner approach and I'm going to explain it in detail:
Create a custom module
app/etc/modules/Stack_Form.xml:
<?xml version="1.0"?>
<config>
<modules>
<Stack_Form>
<active>true</active>
<codePool>local</codePool>
</Stack_Form>
</modules>
</config>
app/code/local/Stack/Form/etc/config.xml:
<?xml version="1.0"?>
<config>
<modules>
<Stack_Form>
<version>0.1.0</version>
</Stack_Form>
</modules>
<frontend>
<routers>
<stack_form>
<use>standard</use>
<args>
<module>Stack_Form</module>
<frontName>feedback</frontName>
</args>
</stack_form>
</routers>
</frontend>
<global>
<blocks>
<stack_form>
<class>Stack_Form_Block</class>
</stack_form>
</blocks>
</global>
</config>
This configuration registers the stack_form block alias for own blocks and the feedback front name for own controllers.
Create custom block
app/code/local/Stack/Form/Block/Form.php
class Stack_Form_Block_Form extends Mage_Core_Block_Template
{
public function getFormAction()
{
return $this->getUrl('stack_form/index/post`);
}
}
Here we implemented getFormAction() to generate the URL for our custom controller (the result will be BASE_URL/feedback/index/post).
Create custom controller
app/code/local/Stack/Form/controllers/IndexController.php
class Stack_Form_IndexController extends Mage_Contacts_IndexController
{
public function postAction()
{
// your custom post action
}
}
If the form should behave exactly like the contact form, just with a different email template and additional form fields, there are two solutions that I have outlined at https://magento.stackexchange.com/q/79602/243 where only one of them actually requires a custom controller action to send the form:
If you look at the contacts
controller
used in the form action, you will find that
the transactional template is taken directly from the configuration
all POST data is passed to the template (as template variable data), so that you can add any additional fields to the form
template and use them in the email template. But validation is hard
coded for "name", "comment", "email" and "hideit".
So, if you need a completely different email template or
additional/changed input validation, your best bet is to create a
custom controller with a modified copy of the postAction of
Mage_Contacts_IndexController.
But there is another solution that is a bit limited but without any
custom code involved:
create a hidden input that determines the type of the form. It could be just <input type="hidden" name="custom" value="1" />.
in the contact transactional email template, use the if directive to show different content based on the form type:
{{if data.custom}}
... custom contact form email ...
{{else}}
... standard contact form email ...
{{/if}}
How to use this custom block
You can add the form anywhere in the CMS using this code (CMS directive):
{{block type="stack_form/form" template="path/to/your/form.phtml"}}
If you do this, you need to add "stack_form/form" to the block whitelist under System > Permissions > Blocks!
Or in the layout using this code (layout XML):
<block type="stack_form/form" name="any_unique_name" template="path/to/your/form.phtml" />
Solution without custom module
If you use the solution without custom controller and a single email template mentioned above, you can set the form action using layout XML as well.
To achieve this, we use the feature to call helpers as parameters for block actions. Unfortunately, the core helper does not have a public method to get a URL but the helper from Mage_XmlConnect has, so you can use that one:
<block type="core/template" name="any_unique_name" template="path/to/your/form.phtml">
<action method="setFormAction">
<param helper="xmlconnect/getUrl">
<route>contacts/index/post</route>
</param>
</action
</block>
In the CMS directive you cannot use helpers, so there you would need to put the actual URL:
{{block type="stack_form/form" template="path/to/your/form.phtml" form_action="/feedback/index/post"}}
Since you probably have different CMS pages/blocks in different store views, this should not be a big problem.