I have following MAP which is populating my dropdown list; however, it changes the order of the options.
public static final Map SIZE = new TreeMap(){
{
put("-1"," ");
put("100","100m2");
put("200","200m2");
put("300","300m2");
put("400","400m2");
put("500","500m2");
put("600","600m2");
put("700","700m2");
put("800","800m2");
put("900","900m2");
put("1000","1000m2");
}
;
};
<s:select name="size" label="Size" list="#com.example.Lists#SIZE"/>
Options in dropbox
100m2
1000m2
200m2
300m2
....
TreeMap is sorted based on the natural order of the keys. Try changing your keys to integer:
public static final Map SIZE = new TreeMap(){
{
put(-1," ");
put(100,"100m2");
put(200,"200m2");
put(300,"300m2");
put(400,"400m2");
put(500,"500m2");
put(600,"600m2");
put(700,"700m2");
put(800,"800m2");
put(900,"900m2");
put(1000,"1000m2");
}
;
};
<s:select name="size" label="Size" list="#com.example.Lists#SIZE"/>
Related
I am attempting to use the geotools.org library (Version 24) to write a user-defined function to style my GIS map according to an external data source. The documentation for the GeoTools library includes this tantalizing paragraph in the section on Functions:
When a function is used as part of a Style users often want to calculate a value based on the attributes of the Feature being drawn. The Expression PropertyName is used in this fashion to extract values out of a Feature and pass them into the function for evaluation.
This is exactly what I want to do. However, the documentation includes no actual example of how to do this.
I have spent several days trying various permutations of the Function definition, and I get the same result every time: My user-defined function only receives the geometry attribute, not the extra attributes I have specified.
I have verified that everything else works:
The features are read correctly from the shapefile
The function is actually called
The Feature geometry is passed into the function
Upon completion, the map is drawn
But I cannot get the Geotools library to pass in the additional Feature properties from the shapefile. Has anyone gotten this working, or can you even point me to an example of where this is used?
My current function definition:
package org.geotools.tutorial.function;
import mycode.data.dao.MyTableDao;
import mycode.data.model.MyTable;
import org.geotools.filter.FunctionExpressionImpl;
import org.geotools.filter.capability.FunctionNameImpl;
import org.opengis.feature.Feature;
import org.opengis.filter.capability.FunctionName;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.expression.VolatileFunction;
import org.springframework.beans.factory.annotation.Autowired;
import java.awt.*;
import java.beans.Expression;
import java.util.Random;
public class DataFunction extends FunctionExpressionImpl {
#Autowired
MyTableDao myTableDao;
public static FunctionName NAME =
new FunctionNameImpl(
"DataFunction",
Color.class,
FunctionNameImpl.parameter("featureData1", PropertyName.class),
FunctionNameImpl.parameter("featureData2", PropertyName.class));
public DataFunction() {
super("DataFunction");
}
public int getArgCount() {
return 2;
}
#Override
public Object evaluate(Object feature) {
Feature f = (Feature) feature;
// fallback definition
float pct = 0.5F;
if (f.getProperty("featureData1") != null) {
MyTable temp = myTableDao.read(
f.getProperty("featureData1").getValue().toString(),
f.getProperty("featureData2").getValue().toString());
pct = temp.getColumnValue();
}
Color color = new Color(pct, pct, pct);
return color;
}
}
EDIT: I am invoking the function programmatically through a Style that is created in code. This Style is then added to the Layer which is added to the Map during the drawing process.
private Style createMagicStyle(File file, FeatureSource featureSource) {
FeatureType schema = (FeatureType) featureSource.getSchema();
// create a partially opaque outline stroke
Stroke stroke =
styleFactory.createStroke(
filterFactory.literal(Color.BLUE),
filterFactory.literal(1),
filterFactory.literal(0.5));
// create a partial opaque fill
Fill fill =
styleFactory.createFill(
filterFactory.function("DataFunction",
new AttributeExpressionImpl("featureData1"),
new AttributeExpressionImpl("featureData2")));
/*
* Setting the geometryPropertyName arg to null signals that we want to
* draw the default geomettry of features
*/
PolygonSymbolizer sym = styleFactory.createPolygonSymbolizer(stroke, fill, null);
Rule rule = styleFactory.createRule();
rule.symbolizers().add(sym);
FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(new Rule[] {rule});
Style style = styleFactory.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
I think you want to set up your function to take a pair of Strings or Doubles (or whatever those attributes are) so something like:
public static FunctionName NAME =
new FunctionNameImpl(
"DataFunction",
Color.class,
FunctionNameImpl.parameter("featureData1", Double.class),
FunctionNameImpl.parameter("featureData2", Double.class));
public DataFunction(List<Expression> params, Literal fallback) {
this.params = params;
this.fallback = fallback;
}
then your evaluate method becomes:
#Override
public Object evaluate(Object feature) {
Feature f = (Feature) feature;
// fallback definition
float pct = 0.5F;
Expression exp1 = params.get(0);
Expression exp2 = params.get(1);
if (f.getProperty("featureData1") != null) {
MyTable temp = myTableDao.read(
exp1.evaluate(f, Double.class),
exp2.evaluate(f, Double.class));
pct = temp.getColumnValue();
}
Color color = new Color(pct, pct, pct);
return color;
}
and you would use it in the style using something like:
Fill fill =
styleFactory.createFill(
filterFactory.function("DataFunction",
filterFactory.propertyName("featureData1"),
filterFactory.propertyName("featureData2")));
That's a pretty long winded statement.
I'm building a faceted search which implements WebAPI in .Net and utilizes Knockout on the front end. My search response includes two lists of objects, the Resources (object with data for presentation) and Resource Facets (array of strings).
\"ResourceFacets\": [\r\n \"Book\",\r\n \"Video\",\r\n \"DVD\",\r\n \"eBook\",\r\n \"Audio\"\r\n ]\r\n}"
My ViewModel contains both the facets and the resources along with a presentation object to handle a custom row count:
function ViewModel() {
this.facets = ko.observableArray(results.ResourceFacets);
this.resources = ko.observableArray(results.ResourceResults);
this.resourceRows = ko.computed(function() {
var rows = [],
rowIndex = 0,
itemsPerRow = 2;
var resourceList = this.resources();
for (var index = 0; index < resourceList.length; index++) {
if (!rows[rowIndex]) {
rows[rowIndex] = [];
}
rows[rowIndex].push(resourceList[index]);
if (rows[rowIndex].length == itemsPerRow) {
rowIndex++;
}
}
return rows;
});
};
This allowed me to create a dynamic list of checkboxes to handle the facets and also display the resource results. What I'm trying to do now is add a Select All checkbox which will, by default, select all the boxes. From other examples I've seen, my understanding is that I need an observable property, something like "Selected", on that ResourceFacet. I just feel like that is too much that the API needs to know about my presentation.
So my question is how can I avoid having to add a "selected" bool value to the ResourceFacets but still be able to select all checkboxes or deselect the "All" checkbox when a user deselects a facet?
You can keep the list of booleans necessary to track the selection on a separate member of your view model, in addition to facets and resources. Just create a new observableArray of booleans of the same size of facets and bind those values to the checkboxes.
Another solution is to create the objects necessary to bind the checkboxes on the fly, based on results.ResourceFacets, keeping your API clean. For example:
var realModel = [];
for (var i = 0; i < results.ResourceFacets; i++) {
realModel.push({ name: results.ResourceFacets[i], chkBoxVal: ko.observable(false) });
}
this.facets = ko.observableArray(realModel);
When adding a derived column to a data flow with ezAPI, I get the following warnings
"Add stuff here.Inputs[Derived Column Input].Columns[ad_zip]" on "Add
stuff here" has usage type READONLY, but is not referenced by an
expression. Remove the column from the list of available input
columns, or reference it in an expression.
I've tried to delete the input columns, but either the method is not working or I'm doing it wrong:
foreach (Microsoft.SqlServer.Dts.Pipeline.Wrapper.IDTSInputColumn100 col in derFull.Meta.InputCollection[0].InputColumnCollection)
{
Console.WriteLine(col.Name);
derFull.DeleteInputColumn(col.Name);
}
I have the following piece of code that fixes the problem.
I got it from a guy called Daniel Otykier. So he is propably the one that should be credited for it... Unlesss he got it from someone else :-)
static public void RemoveUnusedInputColumns(this EzDerivedColumn component)
{
var usedLineageIds = new HashSet<int>();
// Parse all expressions used in new output columns, to determine which input lineage ID's are being used:
foreach (IDTSOutputColumn100 column in component.GetOutputColumns())
{
AddLineageIdsFromExpression(column.CustomPropertyCollection, usedLineageIds);
}
// Parse all expressions in replaced input columns, to determine which input lineage ID's are being used:
foreach (IDTSInputColumn100 column in component.GetInputColumns())
{
AddLineageIdsFromExpression(column.CustomPropertyCollection, usedLineageIds);
}
var inputColumns = component.GetInputColumns();
// Remove all input columns not used in any expressions:
for (var i = inputColumns.Count - 1; i >= 0; i--)
{
if (!usedLineageIds.Contains(inputColumns[i].LineageID))
{
inputColumns.RemoveObjectByIndex(i);
}
}
}
static private void AddLineageIdsFromExpression(IDTSCustomPropertyCollection100 columnProperties, ICollection<int> lineageIds)
{
int lineageId = 1;
var expressionProperty = columnProperties.Cast<IDTSCustomProperty100>().FirstOrDefault(p => p.Name == "Expression");
if (expressionProperty != null)
{
// Input columns used in expressions are always referenced as "#xxx" where xxx is the integer lineage ID.
var expression = expressionProperty.Value.ToString();
var expressionTokens = expression.Split(new[] { ' ', ',', '(', ')' });
foreach (var c in expressionTokens.Where(t => t.Length > 1 && t.StartsWith("#") && int.TryParse(t.Substring(1), out lineageId)))
{
if (!lineageIds.Contains(lineageId)) lineageIds.Add(lineageId);
}
}
}
Simple but not 100% Guaranteed Method
Call ReinitializeMetaData on the base component that EzApi is extending:
dc.Comp.ReinitializeMetaData();
This doesn't always respect some of the customizations and logic checks that EzAPI has, so test it carefully. For most vanilla components, though, this should work fine.
100% Guaranteed Method But Requires A Strategy For Identifying Columns To Ignore
You can set the UsageType property of those VirtualInputColumns to the enumerated value DTSUsageType.UT_IGNORED using EzApi's SetUsageType wrapper method.
But! You have to do this after you're done modifying any of the other metadata of your component (attaching other components, adding new input or output columns, etc.) since each of these triggers the ReinitializeMetaData method on the component, which automatically sets (or resets) all UT_IGNORED VirtualInputColumn's UsageType to UT_READONLY.
So some sample code:
// define EzSourceComponent with SourceColumnToIgnore output column, SomeConnection for destination
EzDerivedColumn dc = new EzDerivedColumn(this);
dc.AttachTo(EzSourceComponent);
dc.Name = "Errors, Go Away";
dc.InsertOutputColumn("NewDerivedColumn");
dc.Expression["NewDerivedColumn"] = "I was inserted!";
// Right here, UsageType is UT_READONLY
Console.WriteLine(dc.VirtualInputCol("SourceColumnToIgnore").UsageType.ToString());
EzOleDbDestination d = new EzOleDbDestination(f);
d.Name = "Destination";
d.Connection = SomeConnection;
d.Table = "dbo.DestinationTable";
d.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD;
d.AttachTo(dc);
// Now we can set usage type on columns to remove them from the available inputs.
// Note the false boolean at the end.
// That's required to not trigger ReinitializeMetadata for usage type changes.
dc.SetUsageType(0, "SourceColumnToIgnore", DTSUsageType.UT_IGNORED, false);
// Now UsageType is UT_IGNORED and if you saved the package and viewed it,
// you'll see this column has been removed from the available input columns
// ... and the warning for it has gone away!
Console.WriteLine(dc.VirtualInputCol("SourceColumnToIgnore").UsageType.ToString());
I was having exactly your problem and found a way to solve it. The problem is that the EzDerivedColumn has not the PassThrough defined in it's class.
You just need to add this to the class:
private PassThroughIndexer m_passThrough;
public PassThroughIndexer PassThrough
{
get
{
if (m_passThrough == null)
m_passThrough = new PassThroughIndexer(this);
return m_passThrough;
}
}
And alter the ReinitializeMetadataNoCast() to this:
public override void ReinitializeMetaDataNoCast()
{
try
{
if (Meta.InputCollection[0].InputColumnCollection.Count == 0)
{
base.ReinitializeMetaDataNoCast();
LinkAllInputsToOutputs();
return;
}
Dictionary<string, bool> cols = new Dictionary<string, bool>();
foreach (IDTSInputColumn100 c in Meta.InputCollection[0].InputColumnCollection)
cols.Add(c.Name, PassThrough[c.Name]);
base.ReinitializeMetaDataNoCast();
foreach (IDTSInputColumn100 c in Meta.InputCollection[0].InputColumnCollection)
{
if (cols.ContainsKey(c.Name))
SetUsageType(0, c.Name, cols[c.Name] ? DTSUsageType.UT_READONLY : DTSUsageType.UT_IGNORED, false);
else
SetUsageType(0, c.Name, DTSUsageType.UT_IGNORED, false);
}
}
catch { }
}
That is the strategy used by other components. If you want to see all the code you can check my EzApi2016#GitHub. I'm updating the original code from Microsoft to SQL Server 2016.
So I have some code that dynamically creates an ASP.NET form based on an XML input file. I'm trying to add attributes to the controls at run time and I'm having some weird issues with list items.
My Server Side Code looks something like this:
Me.radioButtonList = New RadioButtonList()
Me.dropDownList = New DropDownList()
Me.listControl = Nothing
If controlType = "dropdown" Then
Me.listControl = Me.dropDownList
Else
Me.listControl = Me.radioButtonList
End If
For Each ansElement As Answer In strAnswers
Dim newListItem = New ListItem(ansElement.AnswerText, ansElement.AnswerText)
If ansElement.ActionID IsNot Nothing AndAlso ansElement.ActionID <> "" Then
newListItem.Attributes.Add("actionID", ansElement.ActionID)
End If
Me.listControl.Items.Add(newListItem)
Next
Me.listControl.ID = controlID
Me.Controls.Add(Me.listControl)
The problem is when I run the code and the page is render the attributes are being added to the proceeding span tag of the control not the input item itself. So the rendered HTML ends up looking like this.
<span actionID="1">
<input id="lst_dynamic_MedIllnesses_0" name="ctl00$MainContentPlaceHolder$FormGenerator1$lst_dynamic_MedIllnesses$lst_dynamic_MedIllnesses_0" value="None" type="checkbox">
<label for="lst_dynamic_MedIllnesses_0">None</label>
</span>
What do I have to do to get the actionID attribute to be added to the actual input control and not the span tag?
Thanks!
I suppose you are talking about RadioButtonList. The problem with it is that it uses RadioButton control, and it has 3 attributes properties - Attributes, InputAttributes and LabelAttributes. Each of them is used for specific html element.
The problem with RadioButtonList, is that it uses just Attributes property, and doesn't use InputAttributes. Here is code of RadioButtonList.RenderItem method:
protected virtual void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
{
if (repeatIndex == 0)
{
this._cachedIsEnabled = this.IsEnabled;
this._cachedRegisterEnabled = this.Page != null && !this.SaveSelectedIndicesViewState;
}
RadioButton controlToRepeat = this.ControlToRepeat;
int index1 = repeatIndex + this._offset;
ListItem listItem = this.Items[index1];
controlToRepeat.Attributes.Clear();
if (listItem.HasAttributes)
{
foreach (string index2 in (IEnumerable) listItem.Attributes.Keys)
controlToRepeat.Attributes[index2] = listItem.Attributes[index2];
}
if (!string.IsNullOrEmpty(controlToRepeat.CssClass))
controlToRepeat.CssClass = "";
ListControl.SetControlToRepeatID((Control) this, (Control) controlToRepeat, index1);
controlToRepeat.Text = listItem.Text;
controlToRepeat.Attributes["value"] = listItem.Value;
controlToRepeat.Checked = listItem.Selected;
controlToRepeat.Enabled = this._cachedIsEnabled && listItem.Enabled;
controlToRepeat.TextAlign = this.TextAlign;
controlToRepeat.RenderControl(writer);
if (!controlToRepeat.Enabled || !this._cachedRegisterEnabled || this.Page == null)
return;
this.Page.RegisterEnabledControl((Control) controlToRepeat);
}
controlToRepeat is that RadioButton, and it specifies only Attributes property and ignores InputAttributes.
I can suggest way to fix it - you can create new class that inherits RadioButtonList, and use it instead of default. Here is code of that class:
public class MyRadioButtonList : RadioButtonList
{
private bool isFirstItem = true;
protected override void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
{
if (isFirstItem)
{
// this.ControlToRepeat will be created during this first call, and then it will be placed into Controls[0], so we can get it from here and update for each item.
var writerStub = new HtmlTextWriter(new StringWriter());
base.RenderItem(itemType, repeatIndex, repeatInfo, writerStub);
isFirstItem = false;
}
var radioButton = this.Controls[0] as RadioButton;
radioButton.InputAttributes.Clear();
var item = Items[repeatIndex];
foreach (string attribute in item.Attributes.Keys)
{
radioButton.InputAttributes.Add(attribute, item.Attributes[attribute]);
}
// if you want to clear attributes for top element, in that case it's a span, then you need to call
item.Attributes.Clear();
base.RenderItem(itemType, repeatIndex, repeatInfo, writer);
}
}
A bit of description - it has isFirstItem property, as RadioButton control that used by it is created in runtime in the first access, so we need to call RenderItem before we can update InputAttrubutes property. So we call it once and send some stub HtmlTextWriter, so it won't be displayed twice. And then after that we just get this control as Controls[0], and for each ListItem we update InputAttributes values.
PS. Sorry, I didn't use VB.Net so control is written in C#
Lots of references for creating lookups out there, but all seem to draw their values from a query.
I want to add a lookup to a field that will add items from a list of values that do not come from a table, query, or any other data source.
Such as from a string: "Bananas, Apples, Oranges"
..or a container ["Bananas", "Apples", "Oranges"]
Assume the string/container is a dynamic object. Drawing from an static enum is not a choice.
Is there a way to create lookups on the fly from something other than a data source?
Example code would be a great help, but I'll take hints as well.
There is the color picker.
Also in the Global you will find pickXxxx such as pickList.
There are others, pickUser, pickUserGroup etc.
Take a look on the implementation. I guess they build a temporary table then displays that. Tables are great!
Update:
To go on you own follow the rules.
For the advanced user, see also: Lookup form returning more than one value.
public void lookup()
{
SysTableLookup sysTableLookup;
TmpTableFieldLookup tmpTableFieldLookup;
Enumerator en;
List entitylist = new list(types::String);
entitylist.addend("Banana");
entitylist.addend("Apple");
en = entityList.getEnumerator();
while (en.moveNext())
{
tmpTableFieldLookup.TableName = en.current();
tmpTableFieldLookup.insert();
}
sysTableLookup = SysTableLookup::newParameters(tableNum(tmpTableFieldLookup), this);
sysTableLookup.addLookupfield(fieldNum(TmpTableFieldLookup, TableName));
//BP Deviation documented
sysTableLookup.parmTmpBuffer(tmpTableFieldLookup);
sysTableLookup.performFormLookup();
}
The above code helps in displaying strings as lookup.
I'm also guessing there's no way to perform a lookup without a table. I say that because a lookup is simply a form with one or more datasources that is displayed in a different way.
I've also blogged about this, so you can get some info on how to perform a lookup, even with a temporary table, here:
http://devexpp.blogspot.com.br/2012/02/dynamics-ax-custom-lookup.html
Example from global::PickEnumValue:
static int pickEnumValue(EnumId _enumId, boolean _omitZero = false)
{
Object formRun;
container names;
container values;
int i,value = -1,valueIndex;
str name;
#ResAppl
DictEnum dictEnum = new DictEnum(_enumId);
;
if (!dictEnum)
return -1;
for (i=1;i<=dictEnum.values();i++)
{
value = dictEnum.index2Value(i);
if (!(_omitZero && (value == 0)))
{
names += dictEnum.index2Label(i);
values += value;
}
}
formRun = classfactory.createPicklist();
formRun.init();
formRun.choices(names, #ImageClass);
formRun.caption(dictEnum.label());
formRun.run();
formRun.wait();
name = formRun.choice();
value = formRun.choiceInt();
if (value>=0) // the picklist form returns -1 if a choice has not been made
{
valueIndex = -1;
for (i=1;i<=conLen(names);i++)
{
if (name == conPeek(names,i))
{
valueIndex = i;
break;
}
}
if (valueIndex>=0)
return conPeek(values,valueIndex);
}
return value;
}
It isn't the most graceful solution, but this does work, and it doesn't override or modify any native AX 2012 objects:
Copy the sysLookup form from AX2009 (rename it) and import it into AX 2012.
We'll call mine myLookupFormCopy.
I did a find/replace of "sysLookup" in the XPO file to rename it.
Create this class method:
public static client void lookupList(FormStringControl _formStringControl, List _valueList, str _columnLabel = '')
{
Args args;
FormRun formRun;
;
if (_formStringControl && _valueList && _valueList.typeId() == Types::String)
{
args = new Args(formstr(myLookupFormCopy));
args.parmObject(_valueList);
args.parm(_columnLabel);
formRun = classFactory.formRunClass(args);
_formStringControl.performFormLookup(formRun);
}
}
In the lookup method for your string control, use:
public void lookup()
{
List valueList = new List(Types::String);
;
...build your valueList here...
MyClass::lookupList(this, valueList, "List Title");
super();
}