client-side values of dynamic control on postback - postback

My custom control contains a repeater that adds a dynamic control into a placeholder on ItemDatabound.
I'm having an issue accessing the updated value of the dynamic control, I am already taking care of rebuilding the dynamic controls on Load but I first need to get to the changes made by the user. I'm just having some trouble understanding where in the Lifecycle is the best place to have access to the updated dynamic control value.
<Repeater>
<ItemTemplate>
<Label /><PlaceHolder />

If anyone who stumbles across this page this is the website that got me on the right track:
http://www.learning2code.net/Learn/2009/8/12/Adding-Controls-to-an-ASPNET-form-Dynamically.aspx
In my case the control I was putting inside my placeholder was also dynamic (data-driven) based on a enum type which determined if a CheckBox, ListBox, Textbox, RadDatePicker, ect. would be inserted in the placeholder.
Since I had a repeater with multiple placeholders instead of just one placeholder containing all of my dynamic controls like the link provided, I implemented my solution as follows.
On the method that adds your dynamic controls to the placeholder (ItemDataBound):
1. Give the dynamic control a unique ID (string)
2. Add the unique ID & enum type to the Dictionary<enum, string> that will be stored in the ViewState
Override the LoadViewState method as follows (this will load your Dictionary<enum, string> array):
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
}
Override the OnLoad method to add the dynamic controls that were cleared on postback:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (IsPostBack)
AddDynamicControlsToPlaceholder();
}
private void AddDynamicControlsToPlaceholder()
{
foreach (RepeaterItem item in reapeater.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
var keyValue = DynamicDictValues.ElementAt(item.ItemIndex);
var plhDynControl = item.FindControl("plhDynControl") as PlaceHolder;
//CreateDynamicControl method uses the key to build a specific typeof control
//and the value is assigned to the controls ID property.
var dynamicControl = CreateDynamicControl(keyValue);
plhItemValue.Controls.Add(dynamicControl);
}
}
}
You still have to implement the code that loops through the repeater and pulls the updated client-side values from the dynamic controls. I hope this helps, it really took a lot of work getting this one solved.

Related

Blazor Text Editor not able to bind value on form (create/edit)

I am using Blazor Text Editor from source below.
Source - https://github.com/Blazored/TextEditor
I successfully integrated it with my create and edit form, however not able to bind-Value to it. Because of this my Data Annotation Validation is failing.
Internally blazor is using Quill Editor, I am not looking for javascript option.
Sample Code of editor
<BlazoredTextEditor #ref="#QuillNative" Placeholder="Enter non HTML format like centering...">
<ToolbarContent>Some editor stuff here</ToolbarContent>
<BlazoredTextEditor
Could anyone please help me. How to bind-Value or correct approach without javascript.
Vencovsky - thanks of you prompt response, I was already aware of these methods however was curious to know if anybody had tried different option.
Below is what I did..
FORM -- This is common form for create & edit. OnValidSubmit will call respective Create/Edit method.
<EditForm Model="Entity" class="contact-form" OnValidSubmit="OnValidSubmit">
//My form fields here
//Commented the validation from that particular field
#*<ValidationMessage For="#(() =>Entity.field)" />*#
<div class="col-sm-1">
<button type="submit" #onclick="***getEditorData***" class="btn"
style="border:2px solid #555555;"><span>Save</span></button>
</div>
</EditForm>
METHOD -- getEditorData() gets fired before OnValidSubmit()
public async void getEditorData()
{
Enity.field = await this.QuillNative.GetHTML();
}
So in my final Entity on OnValidSubmit() I receive all fields along with editor data..
Hope this help if anyone is trying to do so..
Apparently you can't bind a value to it, but you should use the provided methods
Methods
GetText - Gets the content of the editor as Text.
GetHTML - Gets the content of the editor as HTML.
GetContent - Gets the content of the editor in the native Quill JSON Delta format.
LoadContent (json) - Allows the content of the editor to be programmatically set.
LoadHTMLContent (string) - Allows the content of the editor to be programmatically set.
InsertImage (string) - Inserts an image at the current point in the editor.
To use these methods you need a reference of it
#* Getting the BlazoredTextEditor reference*#
<BlazoredTextEditor #ref="#BlazoredTextEditorRef">
#* rest of the code*#
</BlazoredTextEditor>
And in some code in your class you can do
void LoadData(){
//var html = BlazoredTextEditor.LoadHTML(SomeDataToLoad)
BlazoredTextEditor.LoadText(SomeDataToLoad)
}
void ValidateData(){
//var html = BlazoredTextEditor.GetHTML()
var text = BlazoredTextEditor.GetText()
// do something to validate text
}
You can call these methods and use the referece in other methods, this is just an example on how to do it.
here is how I did this:
1- to bind the value on load:
<BlazoredTextEditor #ref="#QuillHtml">
<EditorContent>
#((MarkupString)infoBlock.Description)
</EditorContent>
</BlazoredTextEditor>
to get value on submit
<EditForm Model="infoBlock" OnValidSubmit="LocalOnValidSubmit">
...
#code {
....
[Parameter] public EventCallback OnValidSubmit { get; set; }
BlazoredTextEditor QuillHtml = new BlazoredTextEditor();
private async Task LocalOnValidSubmit()
{
infoBlock.Description = await this.QuillHtml.GetHTML();
await OnValidSubmit.InvokeAsync(this);//to call event handler passed by parent after the HTML prepared for main bound class
}
}

How can I show a hidden column of a grid using the Vaadin Testbench?

I am doing some integration tests, and I have replaced some tables with a grid. At this moment, I have some visible columns by default and other columns are hidden as follows:
column6.setHidable(true);
column6.setHidden(true);
Now I am trying to do some integration tests. For getting the grid, I can use the method (is the only grid present in this view):
$(GridElement.class).first();
This works fine. But for my test (with Vaadin Testbench), I need to check some values that are inside the hidden columns of the grid. I am talking about this button:
I have tried to use the Vaadin debug console to get the name of the button that allows the user to show/hide columns, but the debug console only can select the entire grid element, not this menu.
Also I have check if inside the GridElement exists any kind of already implemented method that give me access to this menu without any success.
Usually, chrome developer tools (or similar for firefox and ie / edge, etc) is your best friend in such cases. So far I'm not aware of anything dedicated for that particular button. However you can workaround this limitation by selecting the items which compose this feature by their specific classes:
The below test method shows a quick implementation which should give you a starting point:
public class GridManipulationTest extends TestBenchTestCase {
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver", "D:\\Kit\\chromedriver_win32\\chromedriver.exe");
setDriver(new ChromeDriver());
}
#After
public void tearDown() throws Exception {
// TODO uncomment below after checking all works as expected
//getDriver().quit();
}
#Test
public void shouldOpenGridColumnVisibilityPopupAndSelectItems() {
// class for the grid sidebar button
String sideBarButtonClass = "v-grid-sidebar-button";
// class for the sidebar content which gets created when the button is clicked
String sideBarContentClass = "v-grid-sidebar-content";
// xpath to select the item corresponding to the necessary column
// there are perhaps more "elegant" solutions, but this is what I came up with at the time
String columnMenuItemXpath = "//*[contains(#class, 'column-hiding-toggle')]/span/div[text()='Name']";
// open the browser
getDriver().get("http://localhost:8080/");
// get the first available grid
GridElement firstGrid = $(GridElement.class).first();
// look for the grid's sidebar button and click it
firstGrid.findElement((By.className(sideBarButtonClass))).click();
// the sidebar content is created outside the grid structure so don't look for it using the grid search context
WebElement sidebarContent = findElement(By.className(sideBarContentClass));
// look for the expected column name and click it
sidebarContent.findElement(By.xpath(columnMenuItemXpath)).click();
}
}
And of course what it looks like in action

Getting selected ListBox values on button Click | ZK

I am very new to ZK framework and trying to customize few things and have struck at one point which I am not sure how to achieve that.
I have a predefined section where I need to show 2 drop down and a button and need to persist those drop down values on button click event.
This is how It has been define in Spring file
<bean id="mybean" parent="parentBean" class="WidgetRenderer">
<property name="detailRenderer">
<bean class="DetailsListRenderer" parent="abstractWidgetDetailRenderer"/>
</property>
</bean>
Here mybean is being used to show main section and I am adding my drop down using this bean while button are being added to detailRenderer.
Save button is bind to onClick event, but I am not sure how I can fetch values from my custom drop down?
I am aware about binding those Dropdown with onClick event but they have to be in same class.
Can any one suggest me how I can fetch values of those drop down.I am creating down down with following code
Listbox listbox = new Listbox();
listbox.appendItem("item1", "item1");
listbox.appendItem("item2", "item2");
This is my button code in another class
protected void createUpdateStatusButton(Widget widget,Div container)
{
Button button = new Button(LabelUtils.getLabel(widget, buttonLabelName, new Object[0]));
button.setParent(container);
button.addEventListener("onClick", new EventListener()
{
public void onEvent(Event event)throws Exception
{
MyClass.this.handleSaveStatusEvent(widget, event);
}
});
}
You may want to listen to the onSelect (I prefer to use Events.ON_SELECT rather than writing the strings) which is more specific to when the Listbox selection changes.
Either way, the key is to get the information you want from the Event passed to your EventListener, rather than going back to your Listbox itself. The basic Event usually carries useful information on getTarget and getData but using more specific events (SelectEvent in this case) will give you access to more relevant info.
button.addEventListener(Events.ON_SELECT, new EventListener<SelectEvent<Listitem, MyDataObject>() {
public void onEvent(SelectEvent<Listitem, MyDataObject> event) {
// Now you can access the details of the selection event..
List<Listitem> selectedItems = event.getSelectedItems();
List<MyDataObject> selectedObjects = event.getSelectedObjects();
}
});
You can find out what events are available for different ZK widgets in their Component Reference documentation.
If I understand the question (I don't think I did in my previous response) you want to gather information from the page (eg: Listbox selection state) when the user clicks a button. Your problem being that you are using disparate classes to compose the page and so don't have access to the various ZK Components when the button is clicked.
(Ignoring the multiple class issue for a minute)
From a high level, there are sort of two camps in the ZK community. The newer MVVM approach suggests the view should push the relevant state to the back end as the user interacts with the front end. This way, the back end never needs to ask for the client state, and when the button is clicked, the values/state are on the server ready to be used.
The other camp binds the client to the server such that the back end always has access to the client Components and when the button is clicked, the values/state can easily be retrieved by interacting with the components.
Another approach is more like what I was talking about in my previous answer, to not bind the back end to the client at all but to rely on event data as much as possible. I favor this approach where it is sufficient.
Now, you're free to choose your favored approach and ZK has lots of documentation on how to work in either of these camps. The question then is where is the client state stored on the server (either pushed there by the client in MVVM or bound there in MVC). I don't think that's a question that can be solved here, that's a software engineering challenge. I personally suggest you take on standard ZK patterns so as not to but heads with the framework. If you really want to go your route, you can grab a reference to the Listbox on the fly like so:
public class Foo {
public static final String LISTBOX_ID = "myListbox";
public void renderListbox(Component parent, MyItem items) {
Listbox listbox = new Listbox();
listbox.setId(LISTBOX_ID);
listbox.setParent(parent);
for (MyItem item : items) {
listbox.appendItem(item.getName(), item);
}
}
}
public class Bar {
#Listen(Events.ON_CLICK + " = #saveButton")
public void saveButtonClicked(Event event) {
Component saveButton = event.getTarget();
Listbox listbox = (Listbox) saveButton.getFellow(Foo.LISTBOX_ID);
Set<Listitem> selection = listbox.getSelectedItems();
// do something
}

Knockout js - Dirty Flag issue

I am using Knockout Js for my view page. I have a requirement where if any editable field changes, I have to enable Save button else not. This is working nicely.
My issue is I have checkboxes too for each row of item. These are observable items in my viewModel. What happens now is when I check or uncheck any checkbox, Knockout considers that as Dirty item and enables the Save button which I don't want.
How can I tackle this?
I am not sure of the exact code that you are using for a dirty flag, but if it involves using ko.toJS in a dependentObservable like this, then there is a trick that you can use to have it skip some observables.
If you create an observable that is a property of a function, then ko.toJS will not find it.
Here are two examples (someFlag and anotherFlag):
function Item(id, name) {
this.id = ko.observable(id);
//create a sub-observable that the dirty flag won't find
this.id.someFlag = ko.observable(false);
this.name = ko.observable(name);
this.dirtyFlag = new ko.dirtyFlag(this);
//or similarly, place an observable on a plain ol' function
this.forgetAboutMe = function() { };
this.forgetAboutMe.anotherFlag = ko.observable(false);
}
Sample here: http://jsfiddle.net/rniemeyer/vGU88/

How to call a MXML class in ActionScript3.0 in Flex 3

I have a page made of custom components. In that page I have a button. If I click the button I have to call another page (page.mxml consisting of custom components). Then click event handler is written in Action-script, in a separate file.
How to make a object of an MXML class, in ActionScript? How to display the object (i.e. the page)?
My code:
page1.mxml
<comp:BackgroundButton x="947" y="12" width="61" height="22"
paddingLeft="2" paddingRight="2" label="logout" id="logout"
click="controllers.AdminSession.logout()"
/>
This page1.mxml has to call page2.mxml using ActionScript code in another class:
static public function logout():void {
var startPage:StartSplashPage = new StartSplashPage();
}
Your Actionscript class needs a reference to the display list in order to add your component to the stage. MXML is simply declarative actionscript, so there is no difference between creating your instance in Actionscript or using the MXML notation.
your function:
static public function logout():void {
var startPage:StartSplashPage = new StartSplashPage();
}
could be changed to:
static public function logout():StartSplashPage {
return new StartSplashPage();
}
or:
static public function logout():void {
var startPage:StartSplashPage = new StartSplashPage();
myReferenceToDisplayListObject.addChild( startPage );
}
If your actionscript does not have a reference to the display list, than you cannot add the custom component to the display list. Adding an MXML based custom component is no different than adding ANY other DisplayObject to the display list:
var mySprite:Sprite = new Sprite();
addChild(mySprite)
is the same as:
var startPage:StartSplashPage = new StartSplashPage();
myReferenceToDisplayListObject.addChild( startPage );
Both the Sprite and the StartSplashPage are extensions of DisplayObject at their core.
You reference MVC in the comments to another answer. Without knowing the specific framework you've implemented, or providing us with more code in terms of the context you are trying to perform this action in, it is difficult to give a more specific answer.
I assume that you are on a page with a set of components and want to replace this set of components on the page with a different set of components. My apologies in advance if this is not what you are trying to do.
You can do this using ViewStacks and switching the selected index on selection -- this can be done either by databinding or by firing an event in controllers.AdminSession.logout() and listening for that event in the Main Page and switching the selectedIndex of the view stack in the handler function.
MainPage.mxml
<mx:ViewStack>
<views:Page1...>
...
<comp:BackgroundButton x="947" y="12" width="61" height="22"
paddingLeft="2" paddingRight="2" label="logout" id="logout"
click="controllers.AdminSession.logout()"/>
</views:Page1...>
<views:Page2 ...>
...
<comp:Comp1 .../>
<comp:Comp2 .../>
</views:Page2>
I think you may use state to do you work.
You may take a look at http://blog.flexexamples.com/2007/10/05/creating-view-states-in-a-flex-application/#more-221
Edit:
I am not sure I fully understand your case.
As I know, you may make a new state in page1.mxml, and name it, eg. secondPageState, and then put the custom component page2.mxml in the secondPageState.
In the controller, you need an import statement to import the page1 component and make a public var for the page1 component, eg. firstPage.
Then, the code will similar to:
public function logout():voild
{
firstPage.currentState = "secondPageState";
}
Another solution:
If you don't like the change state solution, you may try to use the addchild, to add the custom component to your application.

Resources