How can I set the value of a field using javascript (on the client)?
In my view's XML-file, I have:
<field name="zip" />
<field name="city" class="city" />
When the zip changes, I want to do a lookup and set the city (I could do this on the server side with an #api.onchange method, but for performance reasons, I prefer client side).
The lookup works, and I can set the value with:
$('span.city input').val(city);
This puts the city in the input field, but the client doesn't get aware of the change (for instance, I have a server side onchange method to handle other fields, and this method does not get the new city value).
From what I can find, I should call set_value(city) on the field, but how do I find the right object to call the method on?
Please take a look at hr_timesheet_sheet module in static/src/js/timesheet.js. It will give you a clear view of how you can create field and give it a value.
I found a solution. In my zip widget, I find the parent and save the fields list:
openerp.zip_widget = function(instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
var fields; // <-- Variable to keep the field list
instance.web.form.widgets.add('zip', 'instance.zip_widget.zip_lookup');
instance.zip_widget.zip_lookup = instance.web.form.FieldChar.extend({
template: "zip_widget",
start: function() {
this._super();
fields = this.getParent().fields; // <-- Get the field list
},
Now I can set a field value with fields.city.set_value(...);
Related
I'm serializing some data to save them in the database as serialized.
Reason is because i dont want to create 30 columns in the database.
I've overriden the save method and they are being saved successfuly as serialized string. Problem is how to fill the form fields upon editing the fields.
<field
name="tickets][price]"
type="text"
default=""
class="span6" />
How should i edit the loadFormData or how to solve this ?
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState(
'com_buildings.edit.building.data',
array()
);
if (empty($data))
{
$data = $this->getItem();
$data->tickets = unserialize($data->tickets);
}
return $data;
}
Are you aware that serialized data is much harder when it comes to searching? Just wanted to make sure in case you wanted to search for your data at one point (and not only store it).
Having said that, you should replace the following line:
$data->tickets = unserialize($data->tickets);
With this:
if (unserialize($data->tickets) !== FALSE)
$data->tickets = unserialize($data->tickets);
I just started using dgrid, and going through the dTunes sample, I'm unable to find the id associated with each row in the list. This is pretty remedial on my part, but how would I also get the id I sent from the datasource?
define([
'require',
'dgrid/List',
'dgrid/OnDemandGrid',
'dgrid/Selection',
'dgrid/Keyboard',
'dgrid/extensions/ColumnHider',
'dojo/_base/declare',
'dojo/_base/array',
'dojo/Stateful',
'dojo/when',
'dstore/RequestMemory',
'put-selector/put',
'dojo/domReady!'
], function (require, List, Grid, Selection,
Keyboard, Hider, declare, arrayUtil, Stateful,
when, RequestMemory, put) {
var cstsNode = put(listNode, 'div#cstsCars');
...
var cstsList = new TunesList({}, cstsNode);
var dataCSTS = new RequestMemory({ target: require.toUrl('./dataCSTS.json') });
...
dataCSTS.fetch().then(function (cars) {
cstsCars = arrayUtil.map(cars, pickField('Description'));
cstsCars.unshift('All (' + cstsCars.length + ' CSTS Cars' + (cstsCars.length !== 1 ? 's' : '') + ')');
cstsList.renderArray(cstsCars);
});
...
cstsList.on('dgrid-select', function (event) {
var row = event.rows[0];
console.log(row.id); // shows row number. How do I get the real id or other fields?
console.log(row.data); // shows row text that is displayed ("sample text 1")
console.log(row.data.id); // undefined
});
Here is a snippet of sample data like I'm supplying:
[{"id":"221","Description":"sample text 1"},
{"id":"222","Description":"sample text 2"},
{"id":"223","Description":"sample text 3"}]
I'd like to see the id. Instead, row.id returns 1,2 and 3, ie the row numbers (or id dgrid created?).
You haven't really shown a complete example, but given that you're using a store anyway, you'd have a much easier time if you let dgrid manage querying the store for you. If you use dgrid/OnDemandList (or dgrid/List plus dgrid/extensions/Pagination), you can pass your dataCSTS store to the collection property, it will render it all for you, and it will properly pick up your IDs (since Memory, and RequestMemory by extension, default to using id as their identity property).
The most appropriate place to do what you're currently doing prior to renderArray would probably be in the renderRow method if you're just using List, not Grid. (The default in List just returns a div with a text node containing whatever is passed to it; you'll be passing an object, so you'd want to dig out whatever property you actually want to display, first.)
If you want a header row, consider setting showHeader: true and implementing renderHeader. (This is false in List by default, but Grid sets it to true and implements it.)
You might want to check out the Grids and Stores tutorial.
I think the problem might be that I was modeling my code based on the dTunes sample code, which has 3 lists that behave a little differently than a regular grid.
For now, I'm using the cachingStore that is available in the lists. So the way I get the id:
cstsList.on('dgrid-select', function (event) {
var row = event.rows[0];
var id = storeCSTS.cachingStore.data[row.id - 1].id; // -1 because a header was added
console.log(id);
});
I'm not sure whether this will work if I ever try to do sorting.
I have two textboxes
<div>#Html.TextBoxFor(model=>model.Voyage_ID, new{id="VID"})<br /></div>
<div>#Html.EditorFor(model=>model.Arrived, new { #id = "arrived",})</div>
The first is updated dynamically from json based on the selected index of a dropdownlist. In the same manner, I wish to display the second field (and many more other fields that are) associated with the id captured in VID .
How can I accomplish this?
You can use jQuery .change() method:
$(document).ready(function(){
$('#VID').change(function(){
var currentValue = $(this).val(); //get current value of the input
//here comes your logic
});
})
I have a page built in ASP.NET MVC 4 that uses the jquery.validate.unobtrusive library for client side validation. There is an input that needs to be within a range of numbers. However, this range can change dynamically based on user interactions with other parts of the form.
The defaults validate just fine, however after updating the data-rule-range attribute, the validation and message are still triggered on the original values.
Here is the input on initial page load:
<input id="amount" data-rule-range="[1,350]" data-msg-range="Please enter an amount between ${0} and ${1}">
This validates correctly with the message Please enter an amount between $1 and $350 if a number greater than 350 is entered.
After an event fires elsewhere, the data-rule-range is updated and the element looks as such:
<input id="amount" data-rule-range="[1,600]" data-msg-range="Please enter an amount between ${0} and ${1}">
At this point if 500 is entered into the input it will fail validation with the same previous message stating it must be between $1 and $350. I have also tried removing the validator and unobtrusiveValidation from the form and parsing it again with no luck.
$('form').removeData('validator');
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
Is there a clean way to change the validation behavior based on the input attributes dynamically?
As Sparky pointed out changing default attributes dynamically will not be picked up after the validation plugin has been initialized. To best work around this without rewiring how we register validated fields and rules, I found it easiest to register a custom adapter in the unobtrusive library:
jQuery.validator.unobtrusive.adapters.add("amount", {}, function (options) {
options.rules["amount"] = true;
options.messages["amount"] = function () { return $(options.element).attr('data-val-amount'); };
});
jQuery.validator.addMethod("amount", function (val, el, params) {
try {
var max = $(el).attr('data-amount-max');
var min = $(el).attr('data-amount-min');
return val <= max && val >= min;
} catch (e) {
console.log("Attribute data-amount-max or data-amount-min missing from input");
return false;
}
});
Because the message is a function, it will be evaluated every time and always pick up the latest attribute value for data-val-amount. The downside to this solution is that everytime there is a change we need to change all three attributes on the input: data-amount-min, data-amount-max, and data-val-amount.
Finally here is the input markup on initial load. The only attribute that needs to be present on load is data-val-amount.
<input id="amount" data-val-amount="Please enter an amount between ${0} and ${1}" data-val="true">
You cannot change rules dynamically by changing the data attributes. That's because the jQuery Validate plugin is initialized with the existing attributes on page load... there is no way for the plugin to auto re-initialize after dynamic changes are made to the attributes.
You must use the .rules('add') and .rules('remove') methods provided by the developer.
See: http://jqueryvalidation.org/rules/
you can try this one:
// reset the form's validator
$("form").removeData("validator");
// change the range
$("#amount").attr("data-rule-range", "[1,600]");
// reapply the form's validator
$.validator.unobtrusive.parse(document);
charle's solution works! you cannot have model attributes to use it though, I build my inputs like:
#Html.TextBoxFor(m => Model.EnterValue, new
{
#class = "form-control",
id="xxxx"
data_val = "true",
data_val_range = String.Format(Messages.ValueTooBig, Model.ParamName),
data_val_range_max = 6,
data_val_range_min = 2,
data_val_regex_pattern = "^\\d+(,\\d{1,2})?$"
})
and then in javascript:
$("form").removeData("validator");
$("#xxxx").attr('data-val-range-max', 3)
$("#xxxx").attr('data-val-range-min', 0)
$.validator.unobtrusive.parse(document);
I'm creating dijit widget from input:
<input name="serviceName" type="text"/>
input = new ValidationTextBox({required: true}, query('[name=serviceName]')[0])
I have a lot of inputs and I want to batch-process them, giving them to separate function.
The problem is, that I can't find in docs, how to get the input name back from widget (which can be also Select, DateBox etc., neither I can find that property inspecting element in Firebug
function processInput(input) {
var inputName = ???
}
I've tried input.name and input.get('name'), but they are returning undefined.
When instantiating your widget programmatically, properties are usually not copied. It's only when you use declarative markup that these properties are copied. This means that the name property is not copied from your original input node, so it's in fact empty.
When creating your ValidationTextBox, just provide the name property like the example below:
var inputNode = query('[name=serviceName]')[0];
var input = new ValidationTextBox({
required: true,
name: inputNode.name
}, inputNode);
You can then retrieve the name with either input.name or input.get('name').
I also made an example JSFiddle.