I am using the BindingContext to generate the table and don't want a default value chosen.
My Class has this field:
[RadioSelection ("Model:")]
public int model = -1;
public IList<string> Model;
It is then added to the Root:
car = new AddCar () {
Model = new List<string>(){"ES 250","ES 300","ES 330","ES 350"}
};
bc = new BindingContext (this, car, "Add Your Vehicle");
this.Root = bc.Root;
However the UI renders a selected value "ES 250" instead of a blank value:
Add a null or empty value to the beginning of your list. Otherwise your only option is to modify MT.Dialog to behave the way you want.
Related
Here is what I exactly want to achieve but didn't have an answer. What's best practice to get the uid of CMSParagraphComponent on the storefront?
DefaultCMSComponentService
protected Collection<String> getEditorProperties(AbstractCMSComponentModel component, boolean readableOnly) {
String code = component.getItemtype();
if (!this.cEditorProperties.containsKey(code)) {
LOG.debug("caching editor properties for CMSComponent [" + component.getItemtype() + "]");
List<String> props = new ArrayList();
Collection<String> systemProps = this.getSystemProperties(component);
Set<AttributeDescriptorModel> attributeDescriptors = this.getTypeService()
.getAttributeDescriptorsForType(this.getTypeService().getComposedTypeForCode(code));
Iterator var8 = attributeDescriptors.iterator();
while (true) {
AttributeDescriptorModel ad;
String qualifier;
do {
do {
if (!var8.hasNext()) {
this.cEditorProperties.put(code, props);
return (Collection) this.cEditorProperties.get(code);
}
ad = (AttributeDescriptorModel) var8.next();
qualifier = ad.getQualifier();
} while (systemProps.contains(qualifier));
} while (readableOnly && !ad.getReadable());
props.add(qualifier);
}
} else {
return (Collection) this.cEditorProperties.get(code);
}
}
public Collection<String> getSystemProperties(AbstractCMSComponentModel component) {
String code = component.getTypeCode();
if (!this.cSystemProperties.containsKey(code)) {
LOG.debug("caching system properties for CMSComponent [" + component.getTypeCode() + "]");
List props = null;
try {
props = (List) Registry.getApplicationContext().getBean(code + "SystemProperties");
} catch (NoSuchBeanDefinitionException var5) {
LOG.debug("No bean found for : " + code + "SystemProperties", var5);
props = this.getSystemProperties();
}
this.cSystemProperties.put(code, props);
}
return (Collection) this.cSystemProperties.get(code);
}
It's not being populated because it's considered as the system property. Hence, as per the above logic system property will not be consider as redable property.
Now question is, How hybris get the list of system property for the given type? In another words, where this Registry.getApplicationContext().getBean(code + "SystemProperties") bean declare?
EDIT: The fact I know is, if Property attribute of AttributeDescriptor is set to false then it consider as system property. But when I checked for uid AttributeDescriptor, it (Property attribute) already set true.
There are some functionalities oob in hybris that uses the uid inside a view. For example the SearchPageController. To be more specific, let's take a look at this method :
private static final String COMPONENT_UID_PATH_VARIABLE_PATTERN = "{componentUid:.*}";
...
#ResponseBody
#RequestMapping(value = "/autocomplete/" + COMPONENT_UID_PATH_VARIABLE_PATTERN, method = RequestMethod.GET)
public AutocompleteResultData getAutocompleteSuggestions(...){
final SearchBoxComponentModel component = (SearchBoxComponentModel) cmsComponentService.getSimpleCMSComponent(componentUid);
}
The actual COMPONENT_UID_PATH_VARIABLE_PATTERN value is in the searchboxcomponent.jsp :
<spring:url value="/search/autocomplete/{/componentuid}" var="autocompleteUrl" htmlEscape="false">
<spring:param name="componentuid" value="${component.uid}"/>
</spring:url>
How does this work? Every time you type something, a call to this endpoint is made, with the component uid extracted using ${component.uid}.
Why does this work? Let's take a look at the productLayout1Page.jsp and take a simple tag from there:
<cms:pageSlot position="CrossSelling" var="comp" element="div" class="productDetailsPageSectionCrossSelling">
<cms:component component="${comp}" element="div" class="productDetailsPageSectionCrossSelling-component"/>
</cms:pageSlot>
Now we see that there is a <cms:component component=${..}.../> tag which reference a component instance and you can access it using ${component.attributeName} inside the component's jsp.
It seems not easy to get the uid on the storefront. But I have managed it like this
Create a dynamic attribute and return uid value from the getter method
Now you can populate this dynamic attribute on the frontend
I am trying to add entries to the CRMSourcesAttribute class for more options in the Opportunities Dropdown Box.
I see PXAttributeExtension but apparently this is not meant for developers as I cannot provide a constructor for the base class PXStringListAttribute where the actual values are set.
There must be a simple way to add entries to that dropdown box!
You don't even need to do any customization or programming to change this list. By adding the screen to Automation Steps screen, you can put the Source field in the Fields tab of the automation definition and override the combo box values. Please note that if you're trying that with Acumatica 5.0, you may need to remove the "Opportunities" list as entry point from the generic inquiries, otherwise it will interfere with your selection when you try to select the Opportunities screen from the Automation Steps.
If you want to do it via programming - you'd need to replace the CRMSourcesAttribute on the field with your own version of this attribute. This attribute is fairly simple and is only derived from PXStringList attribute:
public class CRMSourcesAttribute : PXStringListAttribute
{
public const string _WEB = "W";
public const string _PHONE_INQ = "H";
public const string _REFERRAL = "R";
public const string _PURCHASED_LIST = "L";
public const string _OTHER = "O";
public CRMSourcesAttribute() :
base(new[] { _WEB, _PHONE_INQ, _REFERRAL, _PURCHASED_LIST, _OTHER },
new[] { Messages.Web, Messages.PhoneInq, Messages.Referral, Messages.PurchasedList, Messages.Other })
{
}
}
I'm new in the ASP.NET Framework, I've read the fundamental and have some understanding(theory) on the framework but not much in practice.
I'm struggling with the dropdownlistfor helper method, it comes down to having a weird behavior when i attempt to change the value of the selected item programatically.
In my controller i have the Index action method that receives a parameter of type Tshirt, inside this action method i set the property named Color of the Tshirt object with a value of 2.
In the view (strongly typed) i have a list of colors and pass this list as an argument for the constructor of the ColorViewModel class that will be in charge of returning SelectListItems for my list of colors.
In the view I then set the Selected property of my ColorViewModel object with the value coming from model.Color, now i have set everything so that when i call
#Html.DropDownListFor(x => x.Color, cvm.SelectItems, "Select a color")
I will have my dropdown displayed with the selected item.
When the request(GET) is performed the page is rendered by the browser and the dropdownlist appears with the correct value selected that was established with the value 2 in the Index action method, the dropdown displays "Blue" this is correct.
Then if i select a different item in the dropdownlist (RED, having an id of one) and submit the form, the Save action method is called and i know that the model is reaching the action method with a model.Color=1, which is correct.
Then i decide to redirect to the index action method passing the model object, the index action method changes the Color property back to 2, so when the page is rendered it should display again the value of Blue in the dropdown, but it doesn't, it displays Red.
if you comment out the following line in the Save action method you will get a different behavior.
//tshirt.Color = 3;
i know this logic im following doesnt make much sense from a bussines logic perspective, im just trying to understand what i am doing wrong to not get the expected result.
Given the following model
public class Color
{
public int Id { get; set; }
public string Description { get; set; }
}
I Create the following view model
public class ColorViewModel
{
public int Selected { get; set; }
private List<Color> Colors;
public IEnumerable<SelectListItem> SelectItems { get { return new SelectList(this.Colors, "Id", "Description", this.Selected); } }
private ColorViewModel() { }
public ColorViewModel(List<Color> colors)
{
this.Colors = colors;
}
}
This is my Controller
public class HomeController : Controller
{
[HttpGet()]
public ActionResult Index(Tshirt tshirt)
{
tshirt.Color = 2;
Tshirt t = new Tshirt();
t.Color = tshirt.Color;
return View(t);
}
[HttpPost()]
public ActionResult Save(Tshirt tshirt)
{
//tshirt.Color = 3;
return RedirectToAction("Index", tshirt);
//return View("Index",tshirt);
}
}
And Finally my View
#{
List<Color> colors = new List<Color>(){
new Color(){Id=1, Description="Red"},
new Color(){Id=2, Description="Blue"},
new Color(){Id=3, Description="Green"}
};
ColorViewModel cvm = new ColorViewModel(colors) { Selected = Model.Color };
}
#using(#Html.BeginForm("Save","Home")){
#Html.DropDownListFor(x => x.Color, cvm.SelectItems, "Select a color")
<input type="submit" />
}
I have uploaded the complete code: VS Solution
Because when you redirect, you are passing the updated model
return RedirectToAction("Index", tshirt);
Is there a way to store an identifier of a model object or the model object itself in a JavaFX 2 TreeItem<String>? There is just Value to store the text...
I'm populating a TreeView from a list of model objects, and need to find it when the user clicks a node. I'm used to work with Value and Text in .NET Windows Forms or HTML and I am afraid I cannot adapt this way of thinking to JavaFX...
You can use any objects with TreeView, they just have to override toString() for presenting or extend javafx.scene.Node
E.g. for next class:
private static class MyObject {
private final String value;
public MyObject(String st) { value = st; }
public String toString() { return "MyObject{" + "value=" + value + '}'; }
}
TreeView should be created next way:
TreeView<MyObject> treeView = new TreeView<MyObject>();
TreeItem<MyObject> treeRoot = new TreeItem<MyObject>(new MyObject("Root node"));
treeView.setRoot(treeRoot);
I have the same issue as the OP. In addition I want to bind the value displayed in the TreeItem to a property of the object. This isn't complete, but I'm experimenting with the following helper class, where I'm passing in the "user object" (or item) to be referenced in the TreeItem, and a valueProperty (which, in my case, is a property of the item) to be bound to the TreeItem.value.
final class BoundTreeItem<B, T> extends TreeItem<T> {
public BoundTreeItem(B item, Property<T> valueProperty) {
this(item, valueProperty, null);
}
public BoundTreeItem(B item, Property<T> valueProperty, Node graphic) {
super(null, graphic);
itemProperty.set(item);
this.valueProperty().bindBidirectional(valueProperty);
}
public ObjectProperty<B> itemProperty() {
return itemProperty;
}
public B getItem() {
return itemProperty.get();
}
private ObjectProperty<B> itemProperty = new SimpleObjectProperty<>();
}
I would like to ignore certain properties when mapping deep (ie levels > 1) object models.
The following test works fine:
class Foo
{
public string Text { get; set; }
}
class Bar
{
public string Text { get; set; }
}
Mapper.CreateMap<Foo, Bar>()
.ForMember(x => x.Text, opts => opts.Ignore());
var foo = new Foo { Text = "foo" };
var bar = new Bar { Text = "bar" };
Mapper.Map(foo, bar);
Assert.AreEqual("bar", bar.Text);
However when I try to do the same mapping but have Foo and Bar as properties on a parent class the following test fails:
class ParentFoo
{
public Foo Child { get; set; }
}
class ParentBar
{
public Bar Child { get; set; }
}
Mapper.CreateMap<ParentFoo, ParentBar>();
Mapper.CreateMap<Foo, Bar>()
.ForMember(x => x.Text, opts => opts.Ignore());
var parentFoo = new ParentFoo
{
Child = new Foo { Text = "foo" }
};
var parentBar = new ParentBar
{
Child = new Bar { Text = "bar" }
};
Mapper.Map(parentFoo, parentBar);
Assert.AreEqual("bar", parentBar.Child.Text);
Instead of ignoring the text of the Child class (ie left it as "bar") automapper sets the value to null. What am I doing wrong with my mapping configuration?
There are two ways Automapper can perform the mapping. The first way is to simply give Automapper your source object and it will create a new destination object and populate everything for you. This is the way most apps use Automapper. However, the second way is to give it both a source and an existing destination and Automapper will update the existing destination with your mappings.
In the first example, you're giving it an existing destination value so Automapper will use that. In the second example, Automapper is going to do the mapping for ParentFoo and ParentBar, but when it gets to the Child, it's going to create a new Child and then do the mapping (this is the default behavior). This results in the Text property being null. If you want to use the existing Child object, you'll need to configure Automapper to do that with UseDestinationValue:
Mapper.CreateMap<ParentFoo, ParentBar>()
.ForMember(b => b.Child, o => o.UseDestinationValue());
This makes your test pass (as long as you get rid of the first space when setting the parentBar.Child.Text!).