I've been asked to include a link in an error message when the Email address for a registration is already in use.
The validation for this property is done with a IValidatableObject.Validate function on the model. My validate function looks like so...
Public Overridable Function Validate(validationContext As ValidationContext) As IEnumerable(Of ValidationResult) Implements IValidatableObject.Validate
Dim results = New List(Of ValidationResult)()
....
If Not EmailAvailable(Email) Then
results.Add(New ValidationResult("The email address is not available. Forgot Password?", {"Email"}))
End If
Return results
End Function
In my views, I'm using a custom "MyValidationSummary" extension function to format the errors nicely.
The extension function does this...
....
Dim ul = New TagBuilder("ul")
For Each key In helper.ViewData.ModelState.Keys
For Each e In helper.ViewData.ModelState(key).Errors
Dim li = New TagBuilder("li") With {
.InnerHtml = helper.Encode(e.ErrorMessage)
}
ul.InnerHtml += li.ToString()
Next
Next
container.InnerHtml += ul.ToString()
Return New MvcHtmlString(container.ToString())
I know I could just remove helper.Encode, and just output the message as raw html, but this feels a bit hacky.
I'm trying to find a nice way to be able to selectively include html in the messages, while still retaining the default behaviour of encoding plain text messages.
What I thought of doing, is create a custom ValidationResult class, which optionally would include a HTMLString property, so that I can, if I choose, include HTML in the messages.
I can do this, but I don't know if there is any way to get at this custom ValidationResult from MyValidationSummary.
update:
For the time being, I've just added a placeholder tag into the error message, which I then substitute with the actual link in my MyValidationSummary extension method. It's very hacky, but it will work until I've found a better way to do it.
Related
When following the geb page object pattern, it is encouraged to create a static block of values that represent the elements on the page you are attempting to interface with. It is also good to create an at checker. Here is an example:
class SomePage extends Page{
static at = {$(By.xpath("some header or something")).displayed}
static content = {
element1 {$(By.xpath("some xpath1"))}
element2 {$(By.xpath("some xpath2"))}
//so on and so forth
}
}
Now I think I know the answer this question already but could not find the docs to back it up. I am pretty sure that the static content block is initialized once the "at checker" is called from a test script, but I am not sure. If what I am suggesting is true then that would mean something like this:
class SomePage extends Page{
static at = {$(By.xpath("some header or something")).displayed}
def someString
static content = {
element1 {$(By.xpath("//*[contains(text(), ${someString}"))}
element2 {$(By.xpath("some xpath2"))}
//so on and so forth
}
def setSomeString(String x){
this.someString = x
}
}
would be impractical right, or maybe even impossible? This is because in order to call "setSomeString" you need to call the at checker to tell the script which class to reference for method and variable calls, but if you call the at checker that means the static content becomes initialized.
Furthermore, if a webpage has content that doesn't show up upon initial arrival to the webpage, then you would not be able to put that content into the static content block either, since the at checker should be called as soon as you arrive on said webPage.
I am simply looking to confirm or deny that this is the behavior of geb page object. and I would be happy to hear answers describing best practice given the above situation.
also if there is a way to re-initialize the content, I would like to know that too, but I figure there is not.
A content definition is evaluated every time the result of the definition is requested:
def somePage = to SomePage //at checker is executed but the defintion for element1 isn't
somePage.element1 // closure defined for element1 is executed
somePage.element1 // and here again
// many lines of code which trigger additional content to show up on the page
somePage.element1 // closure defined for element1 is executed again
I got a requirement. I have added two text fields Value and Key from structure in Web Content Display portlet.
right now in the portlet i am getting value from hard code like below.
BasicModel model = (BasicModel)requestContext.getFlowScope().get("BasicModel");
if(model == null){
model = new BasicModel();
}
model.setEmployeeId("AB1223344S");
model.setHireDate("01-Jan-2000");
model.setNiNumber("AB123456S");
model.setDateOfBirth("12-Dec-1980");
model.setBasicForm(new BasicDetailsForm());
}
but what i want is to get the value of each attribute from web content. Like, If i have given lfr.intel.empid as key and ABSD1822D as value in the added web content structure field like this.
and we can fetch the value of key like this.
model.setEmployeeId(lfr.intel.empid);
You can write a custom function for this which passes the key to that function, now that function will use the JournalArticleLocalServiceUtil API to get respective value from the DB.
Now you need to find How to fetch values from JournalArticleLocalServiceUtil, which you can google or this link can help you.
Thanks.
Try this, assuming that you could get the JournalArticle object, I've done it using the resourcePrimKey
long resourcePrimKey = 12345; //hard coded the resourcePrimKey
JournalArticle article = JournalArticleLocalServiceUtil.getLatestArticle(resourcePrimKey);
com.liferay.portal.kernel.xml.Document document = SAXReaderUtil.read(article.getContentByLocale("en_US"));
Node keyNode = document.selectSingleNode("/root/dynamic-element[#name='Key']/dynamic-content");
String key = keyNode.getStringValue();
Node valueNode = document.selectSingleNode("/root/dynamic-element[#name='Value']/dynamic-content");
String value = valueNode .getStringValue();
I created an ActivityNode (an Entry) and I can add custom fields with the
setFields(List<Field> newListField)
fonction.
BUT
I am unable to modify these fields. (In this case I try to modify the value of the field named LIBENTITE)
FieldList list = myEntry.getTextFields();
List<Field> updatedList = new ArrayList<Field>();
//I add each old field in the new list, but I modify the field LIBENTITE
for(Field myField : list){
if(myField.getName().equals("LIBENTITE")){
((TextField)myField).setTextSummary("New value");
}
updatedList.add(myField);
}
myEntry.setFields(updatedList);
activityService.updateActivityNode(myEntry);
This code should replace the old list of fields with the new one, but I can't see any change in the custom field LIBENTITE of myEntry in IBM connections.
So I tried to create a new list of fields, not modifying my field but adding a new one :
for(Field myField:list){
if(!myField.getName().equals("LIBENTITE")){
updatedList.add(myField);
}
}
Field newTextField = new TextField("New Value");
newTextField .setFieldName("LIBENTITE");
updatedList.add(newTextField );
And this code is just adding the new field in myEntry. What I see is that the other custom fields did not change and I have now two custom fields named LIBENTITE, one with the old value and the second with the new value, in myEntry.
So I though that maybe if I clear the old list of Fields, and then I add the new one, it would work.
I tried the two fonctions
myEntry.clearFieldsMap();
and
myEntry.remove("LIBENTITE");
but none of them seems to work, I still can't remove a custom field from myEntry using SBT.
Any suggestions ?
I have two suggestions, as I had (or have) similar problems:
If you want to update an existing text field in an activity node, you have to call node.setField(fld) to update the field in the node object.
Code snippet from my working application, where I'm updating a text field containing a (computed) start time:
ActivityNode node = activityService.getActivityNode(id);
node.setTitle(formatTitle()); // add/update start and end time in title
boolean startFound = false;
// ...
FieldList textfields =node.getTextFields();
Iterator<Field> iterFields = textfields.iterator();
while (iterFields.hasNext()) {
TextField fld = (TextField) iterFields.next();
if (fld.getName().equals(Constants.FIELDNAME_STARTTIME)) {
fld.setTextSummary(this.getStartTimeString()); // NOTE: .setFieldValue does *not* work
node.setField(fld); // write updated field back. This seems to be the only way updating fields works
startFound=true;
}
}
If there is no field with that name, I create a new one (that's the reason I'm using the startFound boolean variable).
I think that the node.setField(fld) should do the trick. If not, there might be a way to sidestep the problem:
You have access to the underlying DOM object which was parsed in. You can use this to tweak the DOM object, which finally will be written back to Connections.
I had to use this as there seems to be another nasty bug in the SBT SDK: If you read in a text field which has no value, and write it back, an error will be thrown. Looks like the DOM object misses some required nodes, so you have to create them yourself to avoid the error.
Some code to demonstrate this:
// ....
} else if (null == fld.getTextSummary()) { // a text field without any contents. Which is BAD!
// there is a bug in the SBT API: if we read a field which has no value
// and try to write the node back (even without touching the field) a NullPointerException
// will be thrown. It seems that there is no value node set for the field. We
// can't set a value with fld.setTextSummary(), the error will still be thrown.
// therefore we have to remove the field, and - optionally - we set a defined "empty" value
// to avoid the problem.
// node.remove(fld.getName()); // remove the field -- this does *not* work! At least not for empty fields
// so we have to do it the hard way: we delete the node of the field in the cached dom structure
String fieldName = fld.getName();
DeferredElementNSImpl fldData = (DeferredElementNSImpl) fld.getDataHandler().getData();
fldData.getParentNode().removeChild(fldData); // remove the field from the cached dom structure, therefore delete it
// and create it again, but with a substitute value
Field newEmptyField = new TextField (Constants.FIELD_TEXTFIELD_EMPTY_VALUE); // create a field with a placeholder value
newEmptyField.setFieldName(fieldName);
node.setField(newEmptyField);
}
Hope that helps.
Just so that post does not stay unanswered I write the answer that was in a comment of the initial question :
"currently, there is no solution to this issue, the TextFields are read-only map. we have the issue recorded on github.com/OpenNTF/SocialSDK/issues/1657"
Currently I'm working on TestComplete automation tool. I'm facing a problem in selecting a value from a dropdown using Jscript. It can done easily in javascript by
document.getElementById("id").options[1].selected=true
I cant do it using JScript'. I've tried
Browsers.Item(btIExplorer).Run("Page URL"); //opening the browser and running a URL
browser=Aliases.browser; //creating alias of browser object
page=browser.Page("PageURL"); //creating a page object for the page opened
page.NativeWebObject.Find("id", "defaultLocationBinder_newOrExisting", "input") // This is the dropdown
I'm not able to find any suitable option to select the options in the dropdown which are given in the <option></option> tags
I just wrote this piece of code and was able to do it.
Use the selectedIndex to set the option you want.
use the object spy to check the properties/methods you can use with the object.
function loginDropDown()
{
var dropDown = Sys.Browser("iexplore").Page("*").FindChild("Name","Select(\"myList\")",10,true)
dropDown.selectedIndex = 1
}
The NativeWebObject.Find method returns a native object while you may want to work with a TestComplete wrapper. Use the Find or FindChild method to get such a wrapper and the Clickitem method to select a specific item.
function test()
{
var b = Sys.Browser("iexplore");
b.ToUrl("http://support.smartbear.com/message/?prod=TestComplete");
var page = b.Page("http://support.smartbear.com/message/?prod=TestComplete");
var cBox = page.FindChild("ObjectIdentifier", "ddlRequestType", 20);
cBox.ClickItem("General product question");
}
We have a compound CT, which outputs the code field of one of the component.
The dream-weaver part of CT is as follows:
<!-- TemplateBeginRepeat name="Component.HTMLCode" -->
##Component.HTMLCode##
<!-- TemplateEndRepeat -->
However this CT displays the code field on the page, instead of converting into HTML.
For eg: If the code field has a value as ->
<div align="center" id="loginapp"></div>
Then this same value is displayed on page instead of parsing.
In the page source, we get output as "< ;div align=" ;center" id=" ;loginapp" ;> ;< ;/div> ;"
I know this can be resolved if we use C#.
But is there any way using dreamweaver to stop the conversion of special characters?
You should use dwt to publish the code to server, I mean create new dwt for every code and just paste the code in the dwt. you can use this dwt with emply component or resource type component.
or if you want to use text field, try following tbb code. add this tbb at the end of the template.
public override void Transform(Engine engine, Package package)
{
Regex objExp = new Regex(#"&#\d+;", RegexOptions.IgnoreCase);
Regex objDecExp = new Regex(#"[^0-9]", RegexOptions.IgnoreCase);
this.Initialize(engine, package);
string strPackage = package.GetValue("Output");
strPackage = unescapeHTML(strPackage);
strPackage = objExp.Replace(strPackage, delegate (Match match)
{
string strInput = match.ToString();
strInput = objDecExp.Replace(strInput, "");
int intValue = Convert.ToInt32(strInput);
char strChar = (char)intValue;
return strChar.ToString();
});
strPackage = strPackage.Trim();
Item objOutput = package.CreateStringItem(ContentType.Html, strPackage);
package.PushItem("Output", objOutput);
}
private string unescapeHTML(string strInput)
{
StringBuilder strOutput = new StringBuilder(strInput);
strOutput.Replace(""", """);
strOutput.Replace(" ", " ");
strOutput.Replace("&", "&");
strOutput.Replace("'", "'");
strOutput.Replace("<", "<");
strOutput.Replace(">", ">");
strOutput.Replace("¡", "¡");
strOutput.Replace("¢", "¢");
strOutput.Replace("£", "£");
strOutput.Replace("¤", "¤");
strOutput.Replace("¥", "¥");
strOutput.Replace("¦", "¦");
strOutput.Replace("§", "§");
strOutput.Replace("¨", "¨");
strOutput.Replace("©", "©");
strOutput.Replace("ª", "ª");
strOutput.Replace("¬", "¬");
strOutput.Replace("", "­");
strOutput.Replace("®", "®");
strOutput.Replace("¯", "¯");
strOutput.Replace("°", "°");
return strOutput.ToString();
}
}
If I recall correctly it is depending on your fieldtype, if in your Schema you use a normal text field, then HTML is escaped, if you use a rich text field, it will be resolved.
An option would perhaps be to write a Dreamweaver Custom function which allows you to unescape the field (represent it as an HTML field rather than a text field). As you mentioned you could also do it in a TBB, but the Dreamweaver Custom Functions are directly callable from the DWT Template. Either way I think you indeed need to do some coding yourself.
RenderComponentField has two parameters: bool htmlEncodeResult, and bool resolveHtmlAsRTFContent. Are you using this built in function?
Thanks for your help. After lots of trials with dreamweaver code, we decided to use C# TBB instead which solved the purpose.
Also reading the multiline field as a textfield was one of the mistake we committed. This caused the field value to be displayed on page instead of rendering as a code behind.
We finally solved the issue using "MultilineTextField".