ASP Core Razor Pages two way binding - razor-pages

[BindProperty]
public string Source { get; set; }
[TempData]
public string Destination{ get; set; }
When model binding data to a view item, I am able to capture data from a model when I use the [BindProperty] attribute on a property, and assign it to a property that has the [TempData] attribute. But now, if I want to assign it back, it doesn't work
If I make both of the properties as [Required] and [BindProperty], I cannot capture the data from the source..
Is there a way to do real two way binding so I can copy data back and forth between two properties on each return Page();?

BindProperty allow us to have a two way binding but you will also need an input. This works like this. You set the value of the BindProperty and you create an input which will host the value of the property.
<input asp-for="Source" class="form-control" />
This will have as a result, when you submit the form, all the values in the input controls will be transferred to the equivalent BindProperty value.
If you do not have input, you will loose the value. This is how it works.

Related

Is there a way to prevent creation of a data class item in C# WindowsForms UserControl

If I create a UserControl, to create and edit an instance of a data class e.g. Person in C# WindowsForms (call it PersonControl), the framework automatically adds an instance of Person in PersonControl.Designer with some default values for the properties and fills the item controls with those values. This behavior has a number of side effects which I would like to avoid.
Question: is there a defined way to prevent creation of a data class instance in UserControl.Designer?
I think you missing the DesignerSerializationVisibility attribute. If you have a custom control every public property that you add will automatically be serialized. You can use this attribute to disable the serialization for a property. I also recommend to add the Browsable attribute which will hide the property from the designer. If you want more control over serialization, like you want to serialize only when another property is set to true you can create a special named method which will then called by the designer Defining Default Values with the ShouldSerialize and Reset Methods. There was a MSDN Magazine where a lots of winform learning resource was relased there are some gems about winform internal working. If you interested in you can quickly look trhrough it. My favorite is. Create And Host Custom Designers With The .NET Framework 2.0
Sorry but i didn't mention another attribute DefaultValue You can use the attribute the following way.
public partial class PersonEditControl : UserControl
{
[DefaultValue(null)] // This attribute tells the designer if the property value matches what we specified in the attribute(null) it should not store the property value.
public PersonData? Person { get; set; }
public PersonEditControl()
{
InitializeComponent();
}
}

Access a component of a custom control

I have a custom Control which I'll call ccViewTemplate with this code in it:
<xp:repeat id="repeatData" rows="30"
value="#{viewEntry}" var="veData"
first="#{javascript:return (sessionScope.ssFirst != null)?sessionScope.ssFirst:0;}">
<xp:panel id="panelSelect">
<xp:callback facetName="viewBodyFacet" id="callback1"></xp:callback>
</xp:panel><!-- panelSelect -->
</xp:repeat>
the database view (viewEntry) is also defined in ccViewTemplate and defined based on several custom properties. ccViewTemplate is then added to another custom Control called ccFinalView. Where the custom properties are entered, and the content of the display is entered into viewBodyFacet. I have access to veData and a everything works great to this point. In the viewBodyFacet I have a link that does a redirect to open the document which also works fine. However, in the link I want to get the repeatData Property First and store it so that it returns to the correct page of the repeat. I use this code:
sessionScope.put('ssFirst',getComponent("repeatData").first);
However, the code can not find the getComponent("repeatData") because it is inside ccViewTemplate and not accessible. Is there a way to get the component repeatData from the ccViewTemplate while in ccFinalView which contains ccViewTemplate.
I have done getComponent("ccViewTemplate") and I have the handle to the custom Control, but
getComponent("ccViewTemplate").getComponent("RepeatData").first fails. So is there a way to pull a value from a component 'inside' a custom control from 'outside' the custome control?
looked a little further and found this:
var rtn = getComponent("ccViewTemplate").getPropertyMap().getProperty("repeatData");
It does not generate an error but returns nothing, if I add
var rtn = getComponent("ccViewTemplate").getPropertyMap().getProperty("repeatData").first;
I get an error getComponent() is null
Hope this makes sense.
From what I understand, this is a perfect job for a java bean. The bean can even keep a default value.
public class Controller{
public String value;
public Controller(){
value = "default_value";
}
public String getValue(){return value;}
public void setValue(String value){this.value=value}
}
In this fashion, the value will be available as soon as the object is created. pressing the button then sets the value with javascript,
ControllerBean.setValue("thisValue");
and you can read the value
ControllerBean.getValue();
This question shows how to configure the bean: How to set up a managed bean to work with Notes document
By setting this to, say the viewScope, you can then access the value anywhere you need regardless of whether or not it is in a custom control or main page. I highly recommend this approach. It just means possibly rethinking your custom control structure.
EDIT
Extra ideas include having an enum that maintains the views,
public enum Views{
VIEW_1("viewAlias", "urlParam")
private String vwAlias;
private String urlParam;
private Views(String alias, String param){
vwAlias = alias;
urlParam = param;
}
// public getters
}
And then in your controller you can get the view string:
1. By seeing if a view param is included in the URL
2. If a cookie value is set
3. Take the hard coded default
Clicking the change view action then sets the cookie value and changes the view parameter and redirects.
This is all extra ideas, but it is how I build my view controllers. I will be doing a tutorial on that soon.

Passing strongly-typed data from a View to a Controller

I've got a stringly-type view defined using #model MyNamespace.Customer with a form created using Html.BeginForm( "NewCustomer", "CustomerReg", FormMethod.Post ) helper.
The NewCustomer action on my CustomerRegController controller looks like
[HttpPost]
public ViewResult NewCustomer( MyNamespace.Customer objCustomer )
I am "filling" from model-bound fields on the page a portion of the Customer fields.
When I submit I get into the correct action, but the objCustomer is all initial values. I though I could pass strongly-typed data that way; am I doing something wrong?
The fact that your view is strongly typed to #model MyNamespace.Customer doesn't mean that this model will somehow be automagically posted to your action when the form is submitted. Basically you need to have input fields for each property you want to retrieve inside your form if you want this property to be passed to your POST action.
Also make sure that this Customer object is a POCO with a default (parameterless) constructor where each property you would like to retrieve has public getters and setters. Otherwise the default model binder will never be able to deserialize the request to this model. The ideal solution to this problem is to use a view model which is a class that you specifically design to meet the requirements of your view and stop passing your domain models to it. This view model will of course have a default constructor and public setters and getters for all properties you would like to retrieve.

Save all rows in an h:dataTable

I have a Facelets page with a h:dataTable. In each row of the h:dataTable, i am displaying some enabled and disabled services of a user.Here is the model object
public class ServiceList {
private long userId;
private long serviceGroupId;
private String serviceGroupName;
private long serviceId;
private String serviceName;
private String serviceUrl;
private String serviceState;
public UserServiceList() {
}
//getters and setters....
}
These are the details i am displaying in a single row of a dataTable.
serviceState in the above model object is either 'Y' or 'N'.
my problem is the application user should be able to update the servicestate of all rows of a dataTable at once and update them in the backend database.
1)what additional JSF component do i need to use inside dataTable to achive this? I am thinking of adding one more column with h:selectOneradio
2)How do i get which rows are selected and what status they have set?
I am kind of newbee to JSF.Please help.
Update:At present what i am having is two buttons namely 'Disable Service' and 'Enable Service' in the footer section of the table.
Onclick of Disable Service i am navigating to another page where i show the application user the list of enabled services to disable
And vice-versa for Enabled service button click.
So, let's say you in your Managed Bean you have a list of services you would like the user to edit:
List<Service> serviceList;
You take this List to be displayed in the data table.
<h:dataTable value="#{yourManagedBean.serviceList}" ... >
Then you can implement a commandButton that has either an action or an actionListener which points to a certain method of your managed bean, like this:
<h:commandButton action="#{yourManagedBean.saveAllAction}" ... >
And the corresponding method to save 'em all is quite straight-forward. You iterate over the managed bean field serviceList and persist every single entry (however you persist them, like calling the EntityManager when using Hibernate or any DAO class in between, you name it.)
Concerning the service status: I'd preferably use a selectBooleanCheckbox for toggling the status, since it's probably a boolean value.
Edit after comment 1:
You have the serviceStatus in your Service class. Currently it's a string, but I suppose it should be boolean to toggle active/inactive. If this property is displayed by the selectBooleanCheckbox it is automatically changed in your corresponding Java class. So calling getServiceStatus() returns true or false, depending on what is selected in the frontend. If you persist the whole Service object then, you don't have to do anything because any modifications made in the frontend HTML elements are automatically projected to the Java object behind it.

Bind h:selectBooleanCheckbox value to int/Integer instead of boolean/Boolean

I have a <h:selectBooleanCheckbox value="#{someBean.prop}"> where prop is a property of type int. Is it really not working straight away? Do I have to implement a custom converter to convert Boolean to int? Does anyone happen to have converter code for that at stock? I read that there is some bug in JSF 2.0 that prevents converters for <h:selectBooleanCheckbox> to be processed. Can anyone confirm that?
I use MyFaces 2, Tomahawk and Tomcat 6.
The <h:selectBooleanCheckbox> should, as its name say, be bound to a boolean or Boolean property. Nothing else. That it allows a converter attribute is actually a bug in the spec. It should never have allowed it.
The problem is more in your model, why would you use an int to represent a boolean state? Change your model to let it be a fullworthy boolean.
If changing the model isn't an option for some reason (a 3rd party API, a stupid architect, or stupid business restrictions, etc), then wrap the model getter/setter in the backing bean like follows
public boolean isChecked() {
return someModel.getSomeInt() != 0;
}
public void setChecked(boolean checked) {
someModel.setSomeInt(checked ? 1 : 0);
}
and use it instead as <h:selectBooleanCheckbox value="#{bean.checked}" />.
just to say MySQL doesn't have boolean as field type choice, and it could be an example for this need.
You can set field as tinyint in MySQL. Actually problem is getting method name when you create a boolean variable. Use method name getChecked() instead of isChecked().

Resources