i have several intboxes under the same window parent. I created a custom validator with custom message for an intbox. For displaying the error message i use a label which i give a unique id. Now i need to use the same constraint for all the intboxes. As in the custom error message i have a unique label id for displaying the error so how do i use the same message for all the intboxes?
Here is the code for my custom validator with custom message:
<zscipt> <![CDATA[
class MyConst implements Constraint, CustomConstraint {
//Constraint//
public void validate(Component comp, Object value) {
if (value == null || ((Integer)value).intValue() >8)
throw new WrongValueException(comp, "values only b/w 0 and 8");
}
//CustomConstraint//
public void showCustomError(Component comp, WrongValueException ex) {
errmsg.setValue(ex != null ? ex.getMessage(): "");
}
}
Constraint ctt = new MyConst();
]]>
Thanks.
There are a couple solutions. First, you could enhance MyConst's constructor to accept Label.
Second, you could use a name pattern. For example, if the label's ID is always a catenation of the textbox's ID and, say, "Error". Then, you could use comp.getFellow(comp.getId()+"Error") to retrieve the label.
In addition, you could use the server-side component selector to get the label.
Related
In page edit mode I want to show a read-only text that is based on a page property value. The text could for example be "A content review reminder email will be sent 2015-10-10", where the date is based on the page published date + six months (a value that will be configurable and therefore can change anytime). So far I've tried to accomplish something like this by adding another property on the page.
I've added the property CurrentReviewReminderDate to an InformationPage class we use. In page edit mode the property name is shown, but it doesn't have a value. How do I do to show the value in page edit mode (preferably as a label)?
[CultureSpecific]
[Display(
Name = "Review reminder date",
Description = "On this date a reminder will be sent to the selected mail to remember to verify page content",
Order = 110)]
[Editable(false)]
public virtual string CurrentReviewReminderDate
{
get
{
var daysUntilFirstLevelReminder =
int.Parse(WebConfigurationManager.AppSettings["PageReviewReminder_DaysUntilFirstLevelReminder"]);
if (CheckPublishedStatus(PagePublishedStatus.Published))
{
return StartPublish.AddDays(daysUntilFirstLevelReminder).ToString();
}
return "";
}
set
{
this.SetPropertyValue(p => p.CurrentReviewReminderDate, value);
}
}
EPiServer internally uses the GetPropertyValue method (i.e. the opposite of SetPropertyValue) when retrieving content for the UI.
This makes sense, otherwise your "made-up" value would be stored as the real value whenever the content is saved. This would make fall-back values etc impossible to implement.
So, this is by-design (and quite wisely so) in EPiServer. :)
However, you can customize how properties work by:
Using custom editors by applying UI hints
Modifying property metadata (for example, to display a generated value as a watermark in a textbox without interfering with the actual value being saved)
I could be misunderstanding what you're trying to do, but off the top of my head it looks like a custom editor could be a viable option for your use case?
Another solution would be to hook into the LoadedPage-event and add the value from there. This might not be the best way performance-wise since you need to do a CreateWritableClone, but depending on the site it might not matter.
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class EventInitialization : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
ServiceLocator.Current.GetInstance<IContentEvents>().LoadedContent += eventRegistry_LoadedContent;
}
void eventRegistry_LoadedContent(object sender, ContentEventArgs e)
{
var p = e.Content as EventPage;
if (p != null)
{
p = p.CreateWritableClone() as EventPage;
p.EventDate = p.StartPublish.AddDays(10);
e.Content = p;
}
}
}
I have a window in WPF. I need to have a validation mechanizm to check all elements at once. If I use IDataErrorInfo there is only ability to validate one object at once in the indexer.
public string this[string columnName]
{
get
{
if (columnName == "Country"))
{
if (string.IsNullOrEmpty(Country))
return "Country can't be empty";
}
return null;
}
}
How can I get all fields of my Window in the validation method?
I think the best way is to declare a custom attribute and decorate the properties you wanna validate with it, and then use Reflection to iterate through those properties based on whether they have that custom attribute.
I have taken the values from database using Entity Framework , I have that a class called EmployeeDetail in that I have one property called JOined AS.
It gives the values as 'F' for fresher and 'E' for experience.. I need to display this value in
DataGrid as Experience or Fresher instead of F or E..
For that I have created the partial class for EmployeeDetail and created one property CustJoinedAs ...
But I didn't get idea to compare the value and return the required value to DataGrid Column...
Here I also have to give each value to DataGrid.. is it automatically bind when I give the property to Column in DataGrid...or any propetyChanged Events have to be Write..
please give a brief idea.. and Code..
Thank you
You can implement the property in partial class like
public partial class EmployeeDetail
{
public string CustJoinedAs
{
get{return this.JoinedAs = "E"? "Experienced" : "Fresh";}
}
}
And bind column of grid to CustJonedAs despite of JoinedAs.
I'm currently using a Gwt CellTable, bound to my GAE/Objectify backend via RPC calls.
All right now! :-)
Then I want to sort columns, so I read http://code.google.com/intl/it-IT/webtoolkit/doc/latest/DevGuideUiCellTable.html#columnSorting
The Async Remote sorting sections shows very well how to get sorting into my AsyncDataProvider but... how can I retrieve the name of the column the user wants to sort?
It shows this code: ColumnSortList sortList = table.getColumnSortList();
But how can I get String names from that? I simply want to know "surname" or "soldDate", the name of the field the column is bound to! Then I will pass it to my rpc service, and use it to sort data server-side query(...).order(<field_name>)
Am I missing something?
UPD: interesting stuff here: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/77a0eaf8086218a6/effb8d3abe69270b#effb8d3abe69270b
You can keep a list of column names ordered as they are in the table:
List<String> columnNames = new ArrayList<String>();
table.addColumn(surnameColumn, "surname");
columnNames.add("surname");
// add the other columns
Then when you need to get the sort column name:
String sortColumnName;
ColumnSortList sortList = table.getColumnSortList();
if (sortList != null && sortList.size() != 0){
Column <MyEntity, ?> sortColumn = (Column <MyEntity, ?>)
sortList.get(0).getColumn();
Integer columnIndex = table.getColumnIndex(sortColumn);
sortColumnName = columnNames.get(columnIndex);
}
// do your rpc call
*where MyEntity is your data object displayed in the cell table.
A bit late to the party, but here's a more straight-forward solution based off of the current documentation (see section 'ColumnSorting with AsyncDataProvider').
When we're adding our columns we can simply set the dataStoreName:
TextColumn<MyData> surname = new TextColumn<MyData>() {
...
}
surname.setSortable(true);
surname.setDataStoreName("surname"); // Set the column name
table.getColumnSortList().push(surname);
table.addColumn(surname, "Last Name"); // eg. A different name for the UI
Then we can retrieve the column's dataStoreName later when sorting:
#Override
protected void onRangedChanged(HasData<MyData> display) {
...
ColumnSortList.ColumnSortInfo info = table.getColumnSortList().get(0);
String sortColumn = info.getColumn().getDataStoreName(); // Get the column name
boolean sortIsAscending = info.isAscending();
rpcService.requestMyData(
sortColumn,
sortIsAscending,
new AsyncCallback<ArrayList<MyData>>() {...}
);
...
}
Using this method we can pass the column name directly to our RPC method. It even allows us to use a different name (eg. the database column name) than the column name used on the UI/client side.
I have used something like this as an application column object.
public class ScrollTableColumn
{
// --------------------------------------------------------------- Field(s)
private int sequence;
private Column column;
private Header header;
private int size;
private int calculatedSize;
private boolean show;
private PartialColumn partialColumn;
private ColumnNameEnum columnName;
}
Now create a HashMap of the above as follows:
Map<Column, ScrollTableColumn> columnMap
= new HashMap<Column, ScrollTableColumn>();
Add all the columns as you create them both in the ScrollTableColumn and in the columnMap.
Finally you can get the required name as:
ColumnSortList sortList = dataTable.getColumnSortList();
Column<?, ?> column = sortList.get(0).getColumn();
ColumnNameEnum = columnMap.get(column);
String name = ColumnNameEnum.getName();
The proper way is to extend the base column class which will allow you to override cell rendering, pass in column configuration via your constructor, and most importantly set the DataStoreName which is where you should store the field name for the column. Lastly you should not reuse the onrangechanged fire, but access the columnsort handler directly by overriding it. on range change and column sort handler should call some type of method that you have to update your grid. I call mine updateGrid for sanity. This allows you to set any grid parameters used by your async request to specific sort column and direction. The main reason you want to use column sort handler is to access the ColumnSort event which contains your sort direction information
your column class that extends the base GWT column. You can also extend date or number columns too.
public GridStringColumn(String fieldName, String text, String tooltip, boolean defaultShown, boolean sortable, boolean hidden) {
super(new TextCell());
setDataStoreName(fieldName);
this.text_ = text;
this.tooltip_ = tooltip;
this.defaultShown_ = defaultShown;
setSortable(sortable);
this.hidden_ = hidden;
}
create your handler
dataGrid.addColumnSortHandler(new DataGridSortEvent());
your sort event class
protected class DataGridSortEvent implements ColumnSortEvent.Handler {
#Override
public void onColumnSort(ColumnSortEvent event) {
ColumnSortList sortList = dataGrid_.getColumnSortList();
if (sortList != null && sortList.size() > 0) {
Column<T, ?> sortColumn = (Column<T, ?>) sortList.get(0).getColumn();
LOG.info("col_sorta: " + event.isSortAscending());
LOG.info("col_index: " + sortColumn.getDataStoreName());
updateDataList();
}
}
}
updateDataList is your method you use to make the actual AJAX request to your server side. rather then logging you sould store this info in private members of your datagrid class so that your request can parameterize them.
you could also make this work for local caching too, just make a copy of the data from your server locally then return a sorted collection of that cached collection, rather then calling the updateDataList method.
Now you do not need to store a separate list for just string names, which is waste of memory not to mention a synchronicity issue if the column order is change from user interaction or whatever.
I've got an application that reads Lead records from Salesforce via the API and I want to link the Lead Owner field to an attribute in the application. The Lead Owner field doesn't up in the list of available fields but all the custom fields do.
So, my first attempt at a solution was to create a custom field that displayed the Lead Owner name. In the SF formula editor, as far as I can tell, it doesn't display the actual data field but instead displays the ID string. Which is pretty meaningless in the context that I need it for.
alt text http://skinny.fire-storm.net/forposting/insertfield.JPG
Is there a way that we can get at the data in the object that the ID string references?
alt text http://skinny.fire-storm.net/forposting/havewant.JPG
I have the RED BOX but need the GREEN BOX.
EDIT: I can't change the application code that calls the API. I can only change salesforce. So, this is more of a salesforce superuser / formula-writer question, not a question about writing code that calls the SF API.
Salesforce allows access to related data through what they call relationship queries. Instead of joining, you specify the query like this:
System.debug([SELECT Owner.Name FROM Lead WHERE Id = '00QS00000037lvv'].Owner.Name);
Try running that in the system log, just replace the lead ID with one that you're looking at.
When accessing the data through the API, the principle is the same, your proxy objects should allow you to access Lead.Owner.Name.
EDIT:
I agree with eyescream, since you can't change the application code, creating an Apex trigger would be the best way to go here. Here's some code to get you started:
trigger Lead_UpdateOwner on Lead(before insert, before update)
{
Map<Id, String> ownerMap = new Map<Id, String>();
for (Lead lead : Trigger.new)
{
ownerMap.put(lead.OwnerId, null);
}
if (ownerMap.size() > 0)
{
for (User[] users : [SELECT Id, Name FROM User WHERE Id IN :ownerMap.keySet()])
{
for (Integer i=0; i<users.size(); i++)
{
ownerMap.put(users[i].Id, users[i].Name);
}
}
for (Lead lead : Trigger.new)
{
lead.OwnerName__c = ownerMap.get(lead.OwnerId);
}
}
}
lead.OwnerName__c would need to be the name of your custom field on the lead object that will hold the owner name. Type Text, length 121.
I had a similar problem, but wanted all the current and future User fields available. Since a custom lookup field to the User is not restricted by formula fields, I created one named
OwnerLookup
on the Opportunity and Account objects, then used a triggers to populate it on creation or edit. For example the Opportunity trigger is this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update) {
if(trigger.isBefore && trigger.isInsert) {
OpportunityTriggerHandler.newOpportunity(Trigger.old, Trigger.new);
}
else if(trigger.isAfter && trigger.isInsert){
//OpportunityTriggerHandler.futureUse(Trigger.new);
}
else if(trigger.isBefore && trigger.isUpdate){
OpportunityTriggerHandler.updateOpportunity(Trigger.new, Trigger.oldMap);
}
else if(trigger.isAfter && trigger.isUpdate){
//OpportunityTriggerHandler.futureUse(Trigger.new, Trigger.oldMap);
}
}
and the OpportunityTriggerHandler class (Apex code) is:
public with sharing class OpportunityTriggerHandler {
public static void newOpportunity( List<Opportunity> oldOpportunitys, List<Opportunity> newOpportunitys ) {
for (Opportunity opp: newOpportunitys) {
updateOwnerData( opp );
}
}
public static void updateOpportunity( List<Opportunity> oldOpportunitys, Map<Id, Opportunity> newOpportunitys ) {
for (Opportunity opp: oldOpportunitys) {
updateOwnerData( opp );
}
}
public static void updateOwnerData( Opportunity opp ) {
opp.OwnerLookup__c = opp.OwnerId;
}
}
I then create Formula fields on the Opportunity/Account objects to get to any of the owner (User) object fields, such as Oppty Owner Name formula field:
OwnerLookup__r.FirstName & " " & OwnerLookup__r.LastName
VLOOKUP function would be a good try, but
it's available only in validation rules, not in field definitions
it can be used only on custom objects and you need data from User
I'd say you need to query from your application for
SELECT Owner.FirstName, Owner.LastName FROM Lead
Other than that... some "after insert, after update" trigger that would populate your custom field when owner changes?
Just posting for completeness sake (and for the Google searches): The issue arises with any object that can be queued, not just Lead, since the source of it is that the owner can refer to either a user (as usual) or a queue object.
This can be resolved using a formula field instead of triggers, like below:
BLANKVALUE(Owner:Queue.QueueName, Owner:User.FirstName & " " & Owner:User.LastName)
Basically, the BLANKVALUE function in the formula checks whether the owner.queuename is blank, and if so gives the name of the user.