GWT: Trouble getting value from a text box - gwt

I'm using GWT 2.4. I'm trying to submit an AJAX request with the only input being the value of a text field on the page. Here is how I attach the handler to the page's button ...
public void onModuleLoad() {
...
final com.google.gwt.dom.client.Element submitElement = Document.get().getElementById(SUBMIT_BUTTON_ID);
final Button submitButton = Button.wrap(submitElement);
...
// Add a handler to send the name to the server
GetHtmlHandler handler = new GetHtmlHandler();
submitButton.addClickHandler(handler);
}
But here's the problem. In my handler, whenever I try and get the value of the text field, it always returns the value entered in the text field when the page was first loaded, as opposed to what the most current value is ...
class GetHtmlHandler implements ClickHandler {
/**
* Fired when the user clicks on the submitButton.
*/
public void onClick(ClickEvent event) {
submitRequest();
}
/**
* Send the name from the nameField to the server and wait for a
* response.
*/
private void submitRequest() {
...
final Element nameFieldElement = DOM.getElementById(Productplus_gwt.NAME_FIELD_ID);
// This always returns an old value.
String docId = nameFieldElement.getAttribute("value");
Anyone know how I can write GWT code inside my handler to return the most current value of a text field given its page id?
Thanks, - Dave

Try using DOM.getPropertyString / DOM.getElementProperty
Following is the javadoc from GWT source for getAttribute function. It clearly says that the support for javascript's "getAttribute" function could be inconsistent for a few browsers and thus Element and subclasses should be used.
Alternatively you can use DOM.getPropertyString to fetch a value which uses object notation of javascript to get te current value
/**
* Retrieves an attribute value by name. Attribute support can be
* inconsistent across various browsers. Consider using the accessors in
* {#link Element} and its specific subclasses to retrieve attributes and
* properties.
*
* #param name The name of the attribute to retrieve
* #return The Attr value as a string, or the empty string if that attribute
* does not have a specified or default value
*/
public final String getAttribute(String name) {
return DOMImpl.impl.getAttribute(this, name);
}
I tried using javascript's "getAttribute" function to get value of a text field in IE8 and FF6. IE gave the updated value of the text field while FF did not. Here is the fiddle
http://jsfiddle.net/GvNu4/

Well like you said it's an AJAX request so whatever code you have on ... the GWT code will continue to run.
You should use the callback of the request and check the value of the nameFieldElement at that moment.

Related

how to set form name directly on symfony3? [duplicate]

With Symfony 2.7, you could customize a form's name in your EntityType class with the method getName()
This is now deprecated. Is there another way to do that with Symfony 3.0 ?
I have custom prototype entry_rows for collections that I would need to use in different forms.
Since the name of the rows is based on the form's name, I would need to change the later in order to use them with a different form.
You should implements the getBlockPrefix method instead of getName as described in the migration guide here.
As example:
/**
* Returns the prefix of the template block name for this type.
*
* The block prefix defaults to the underscored short class name with
* the "Type" suffix removed (e.g. "UserProfileType" => "user_profile").
*
* #return string The prefix of the template block name
*/
public function getBlockPrefix()
{
return "form_name";
}
Hope this help
Depending on how your form is built, there is different ways to set the name of your form.
If you are creating the form through $this->createForm(CustomType::class):
$formFactory = $this->get('form.factory');
$form = $formFactory->createNamed('custom_form_name', CustomType::class);
If you are building the form from the controller directly through $this->createFormBuilder():
$formFactory = $this->get('form.factory');
$form = $formFactory->createNamedBuilder('custom_form_name', CustomType::class);
Look at the FormFactory and FormBuilder APIs for more information.
You can try it, remove prefix on field name
public function getBlockPrefix()
{
return null;
}

In Extbase 6.2, don't use uid for list page

When using Extbase's "show" action:
<f:link.action action="show" arguments="{event : event}">
I would like to look up said event by a special column ('customID').
The actual TYPO3-uid should NOT appear in the URL (with or without RealURL).
The reason is that the data has been imported, and the "real" uid is 'customId'.
There's always #biesior's approach using f:link.page https://stackoverflow.com/a/26145125/160968 – but I thought I'd try it with the official way.
(how) is it possible to do that in extbase/fluid?
This is possible. Let's assume your model Event has a property customId. So you generate your link like this:
<f:link.action action="show" arguments="{event : event.customId}">
The link generated will have a queryString like this:
?tx_myext[event]=9999
The showAction generated by the Extension Builder expects that the UID of the event is passed. The PropertyMapper then fetches the object automatically and assigns it to the view:
/**
* action show
*
* #param \Your\Extension\Domain\Model\Event $event
* #return void
*/
public function showAction(\Your\Extension\Domain\Model\Event $event) {
$this->view->assign('event', $event);
}
But in your case you cannot fetch the object by UID because you passed the customId. So you need to fetch the object yourself:
/**
* action show
*
* #param integer $event
* #return void
*/
public function showAction($event) {
$event = $this->eventRepository->findOneByCustomId($event);
$this->view->assign('event', $event);
}
The annotation #param integer $event tells TYPO3 that the parameter is "just" an integer. You then call the magic method findOneByCustomId from your eventRepository. findOne indicates that you want exactly one Event object back (and not a QueryResult), while the ByCustomId that queries an existing property of your Event model.
Why not use realUrl with lookUpTable? See here: https://wiki.typo3.org/Realurl/manual#-.3ElookUpTable

How to validate inputs and prevent save actions using databinding in eclipse?

I want to create input forms which validate user input and prevent the model from being saved with invalid data. I have been using databinding which works up to a point but my implementation is not as intuitive as I would like.
Imagine an input which contains '123' and the value must not be empty. The user deletes the characters one by one until empty. The databinding validator shows an error decoration.
However, if the user saves the form and reloads it, then a '1' is displayed in the field - i.e. the last valid input. The databinding does not transmit the invalid value into the model.
I have a ChangeListener but this is called before the databinding so at that point the invalid state has not been detected.
I would like the error to be displayed in the UI but the model remains valid (this is already so). Also, for as long as the UI contains errors, it should not be possible to save the model.
/**
* Bind a text control to a property in the view model
**/
protected Binding bindText(DataBindingContext ctx, Control control,
Object viewModel, String property, IValidator validator)
{
IObservableValue value = WidgetProperties.text(SWT.Modify).observe(
control);
IObservableValue modelValue = BeanProperties.value(
viewModel.getClass(), property).observe(viewModel);
Binding binding = ctx.bindValue(value, modelValue, getStrategy(validator), null);
binding.getTarget().addChangeListener(listener);
ControlDecorationSupport.create(binding, SWT.TOP | SWT.LEFT);
return binding;
}
private UpdateValueStrategy getStrategy(IValidator validator)
{
if (validator == null)
return null;
UpdateValueStrategy strategy = new UpdateValueStrategy();
strategy.setBeforeSetValidator(validator);
return strategy;
}
private IChangeListener listener = new IChangeListener()
{
#Override
public void handleChange(ChangeEvent event)
{
// notify all form listeners that something has changed
}
};
/**
* Called by form owner to check if the form contains valid data e.g. before saving
**/
public boolean isValid()
{
System.out.println("isValid");
for (Object o : getDataContext().getValidationStatusProviders())
{
ValidationStatusProvider vsp = (ValidationStatusProvider) o;
IStatus status = (IStatus)vsp.getValidationStatus()
.getValue();
if (status.matches(IStatus.ERROR))
return false;
}
return true;
}
Your best bet is to steer clear of ChangeListeners - as you've discovered, their order of execution is either undefined or just not helpful in this case.
Instead, you want to stick with the 'observable' as opposed to 'listener' model for as long as possible. As already mentioned, create an AggregateValidationStatus to listen to the overall state of the DataBindingContext, which has a similar effect to your existing code.
Then you can either listen directly to that (as below) to affect the save ability, or you could even bind it to another bean.
IObservableValue statusValue = new AggregateValidationStatus(dbc, AggregateValidationStatus. MAX_SEVERITY);
statusValue.addListener(new IValueChangeListener() {
handleValueChange(ValueChangeEvent event) {
// change ability to save here...
}
});
You can use AggregateValidationStatus to observe the aggregate validation status:
IObservableValue value = new AggregateValidationStatus(bindContext.getBindings(),
AggregateValidationStatus.MAX_SEVERITY);
You can bind this to something which accepts an IStatus parameter and it will be called each time the validation status changes.

Getting the record being edited

I am using a custom validator like as:
CustomValidator duplicateValidator;
duplicateValidator = new CustomValidator()
{
#Override
protected boolean condition(Object value)
{
getRecord();
//* .. code to validate this record here *//
}
};
But my page gets stuck in a loop, and by using Firebug, it stucks on getRecord(); part, also the getRecord() == null. Is there another way to get the record that I am editing ?
It could not stuck on getRecord method of CustomValidator because it's code is trivial - nothing could go wrong there:
/**
* #return field values for record being validated
*/
public Record getRecord() {
return record;
}
But depending on what you editing you can try to get edited record from that widget by using their specific methods.
For example for DynamicForm:
form.getValuesAsRecord()
For ListGrid:
listGrid.getEditedRecord(listGrid.getEditRow())

Conditional validation of attributes in extbase: Add errors manually

I need to validate some fields based on values other fields have, within the same model. Since a custom validator only has access to the value it is validating, I can't check other validations there. From inspecting AbstractValidator, I couldn't find a possibility to reach that object the current value is validated.
Is there a solution to validate/add errors in a controller, set errors and render the actual view by keeping the original routine instead of introducing and assigning new objects to the view? Basically I could create a custom $errors var, fill it with errors after having done custom validations and the display it along with the original form errors. But I don't like that workaround approach.
When you add a new model validator, you have access to the other fields of that model
File: test_extension/Classes/Domain/Validator/TestModelValidator.php:
class Tx_TestExtension_Domain_Validator_TestModelValidator extends Tx_Extbase_Validation_Validator_AbstractValidator {
/**
* #param Tx_TestExtension_Domain_Model_TestModel $testModel
* #return boolean
*/
public function isValid($testModel) {
/** #var $testModel Tx_TestExtension_Domain_Model_TestModel */
//Access all properties from $testModel
$field1 = $testModel->getMyField1();
$field2 = $testModel->getMyField2();
}
}
You can also add errors to speific fields, but this code is from TYPO3 4.5, don't know if its still valid:
$error = t3lib_div::makeInstance('Tx_Extbase_Validation_Error', 'The entered value is allready in use.', 1329936079);
$this->errors['field2'] = t3lib_div::makeInstance('Tx_Extbase_Validation_PropertyError', 'field2');
$this->errors['field2']->addErrors(array($error));