I have a form:
<form>
<input type="text" name="email" >
<input type="text" name="phone" >
<input type="button" value="ok" />
</form>
When clicking the button, I'd like to copy the form values to a corresponding model.
I've found Backbone.ModelBinder which will automatically copy values to model whenever the values are changed, but that's not what I want, I just want to copy the values when the button is clicked.
write a custom function into the view where the form is located and bind it to the ok click event:
events: {
...
'click input[name="ok"]': 'copyFormToModel'
...
},
...
copyFormToModel: function() {
var email = $('input[name="email"]').val();
var phone = $('input[name="phone"]').val();
// Perform some sort of validation
this.model.email = email;
this.model.phone = phone;
}
This isn't the prettiest answer, but if you have just one small form in your page, then using some library or plugin might be a bit overkill. If you want to use a plugin or library, then for your case I think backbone-forms could do the trick. It features updating the model bound to the form with a method call rather than every time fields are updated.
This code may be you need:
events: {
...
'click input[value="ok"]': 'collectData2Model'
...
},
...
//suppose employee is your model
collectData2Model: function(e) {
var employee = new Employee();
var attr = {};
$('input').each(function(){
var input = $(this);
attr[input.attr('name')] = input.val();
});
employee.bind('error',function(model,error){
alert(error);
});
// set method will automatically call the model's validate method
employee.set(attr);
}
Related
I have two fields, field1 is a checkbox and field2 is a normal text field. I want to hide a field2 if a field1 is not checked and if
field1 is checked then show field2. For that, I am creating the following code:
odoo.define('survey_inherit.FormView', function (require) {
"use strict";
var FormView = require('web.FormView');
var core = require('web.core');
var QWeb = core.qweb;
var FormView = FormView.extend({
_checkField: function(){
var $checkbox = $('.custom-control-input').val();
if ($checkbox.is(':checked')) {
$('.o_form_label').show();
$('.mandatory_msg_class').show();
}else{
$('.mandatory_msg_class').hide();
}//close else
},
});//close FormController
return FormView;
});
But field2 is not hidden if field1 is not checked and also field2 is not shown if field1 is checked.
Update
My requirement is that I have one form which contains a one2many field with widget many2many_tags and other fields. After clicking on tags of many2many_tags, I want to display the complete records in other fields. I am able to get complete records after a click on tags and also these records are able to put in other fields. After using attrs and opening form view for creating records field2 will never display. But open form view in edit mode after creating a record and click on many2many_tags
field2 is not displayed because of attrs.
Removing attrs and opening form view for creating records field will display(but don't want to display because field1 is not checked) and open form view in edit mode after creating a record, click on many2many_tags work fine as expected.
Attrs condition: attrs="{'invisible':[('constr_mandatory','!=',True)]}"
constr_ mandatory: checkbox field
This is the reason I am not using attrs and trying to achieve with the help of javascript. I hope the provided information is understood. Also, I have updated the question added screenshots for better understanding.
Using attrs:
Using attrs click on many2many_tags
Without using attrs:
You can add a new widget and override the click method.
I did this with a BooleanToggle field.
var basic_fields = require('web.basic_fields');
var Toggle = basic_fields.BooleanToggle.extend({
_onClick: function (event) {
var self = this;
this._super(event);
var node = event.view.$('.custom-control-input');
if(this.value) {
node.show();
} else {
node.hide();
}
},
});
fieldRegistry.add('toggle', Toggle);
You need to add the widget attribute:
field name="field1" widget="toggle"/>
Edit
You need to hide the fields after the form loaded, I suggest to you to override the autofocus function of the FormRenderer.
var FormRenderer = require('web.FormRenderer');
FormRenderer.include({
autofocus: function () {
var self = this;
// In my test I used fields values available in "self.state.data"
if(self.state.model === 'sale.order' && field_value){
var nodes = window.$('.custom-control-input');
nodes.hide();
}
return this._super();
},
});
var $checkbox = $('.custom-control-input').val();
This line set $checkbox to the checkbox's value. May be you just want the checkbox element itself:
var $checkbox = $('.custom-control-input');
Try jQuery
$(function() {
$("#selpoNO").click(function() {
if ($(this).is(":checked")) {
$(".if_pucEntry").show();
} else {
$(".if_pucEntry").hide();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- checkbox -->
<label class="led-label"><input type="checkbox" class="led-btn" name="selpoNO" id="selpoNO" style="width: auto !important;"><strong>Checkbox</strong></label>
<!-- text box -->
<input type="text" class="form-control if_pucEntry" id="" name="" style="display: none;">
<input name="color" type="radio" data-bind="style: { backgroundImage : 'url('+$parents[1].generateSwatchImage($data)+')'}, checked: $parent.selectedOption, checkedValue: $data ,click : $parents[1].onSelectSwatchAddSlick" required />
<select name="size" required aria-required="true" id = "CC-prodDetails-sku-alphaProduct_size" data-bind="validatableTarget: selectedOption, validationOptions: {decorateElement: false, decorateElementOnModified: false}, options: optionValues, optionsText: 'key',
optionsCaption: $data.optionCaption, value: $data.selectedOption, disable: $parent.disableOptions() || $data.disable, optionsAfterRender: function(option, item) { ko.applyBindingsToNode(option, {disable: !item}, item); },onRender : $parent.AlphaSelector(), event : {change : $parents[1].onSelectDropdownOptionAddSlick}">
</select>
handleAddToCart: function() {
notifier.clearError(this.WIDGET_ID);
var variantOptions = this.variantOptionsArray();
notifier.clearSuccess(this.WIDGET_ID);
//get the selected options, if all the options are selected.
var selectedOptions = this.getSelectedSkuOptions(variantOptions);
var selectedOptionsObj = { 'selectedOptions': selectedOptions };
//adding availabilityDate for product object to show in the edit summary
//dropdown for backorder and preorder
var availabilityDateObj = { 'availabilityDate': this.availabilityDate()};
var stockStateObj = { 'stockState': this.stockState()};
var newProduct = $.extend(true, {}, this.product().product, selectedOptionsObj,
availabilityDateObj, stockStateObj);
if(this.selectedSku() && ! this.selectedSku().primaryThumbImageURL){
this.assignSkuIMage(newProduct, this.selectedSku());
}
if (this.variantOptionsArray().length > 0) {
//assign only the selected sku as child skus
newProduct.childSKUs = [this.selectedSku()];
}
newProduct.orderQuantity = parseInt(this.itemQuantity(), 10);
var itemQuantityInCart = this.itemQuantityInCart(newProduct);
var stockAvailable = newProduct.orderLimit&&newProduct.orderLimit<this.stockAvailable()?newProduct.orderLimit:this.stockAvailable();
if ((itemQuantityInCart + parseInt(this.itemQuantity(), 10)) > stockAvailable) {
var notificationMsg = CCi18n.t('ns.productdetails:resources.totalItemQuantityExceeded', {stockAvailable: stockAvailable, itemQuantityInCart: itemQuantityInCart});
notifier.sendError(this.WIDGET_ID, notificationMsg, true);
return;
}
$.Topic(pubsub.topicNames.CART_ADD).publishWith(
newProduct,[{message:"success"}]);
// To disable Add to cart button for three seconds when it is clicked and enabling again
this.isAddToCartClicked(true);
var self = this;
setTimeout(enableAddToCartButton, 3000);
function enableAddToCartButton() {
self.isAddToCartClicked(false);
};
if (self.isInDialog()){
$(".modal").modal("hide");
}
},
I am using required in html tags like input and select but the issue is default popover validation of required seems not to be working
if i use the click on event on button and if i remove that event the require starts working as expected
could someone help ??
<div id="CC-prodDetails-addToCart" data-bind="inTabFlow:(validateAddToCart())" >
<button type = "submit" class="btn primary full-width cart" data-bind="click: handleAddToCart" >
</button>
</div>
return true on the basic click event is the key
jsClick = function () {
console.log('jsClicked');
return true;
};
function MyViewModel() {
var self = this;
self.koClick = function () {
console.log('koClicked');
};
};
ko.applyBindings(new MyViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<button onClick="jsClick()" data-bind="click: koClick">click</button>
i think i have solved the issue i have added a data-bind submit on form tag and called the function there so the functionality and html required behavior both are working fine <form id="PDP_Form" data-bind = "submit : $data.handleAddToCart">
Why not just put a click handler on the submit button?
Heading
Instead of using submit on the form, you could use click on the submit button. However, submit has the advantage that it also captures alternative ways to submit the form, such as pressing the enter key while typing into a text box.
**
Parameters
**
Main parameter
The function you want to bind to the element’s submit event.
You can reference any JavaScript function - it doesn’t have to be a function on your view model. You can reference a function on any object by writing submit: someObject.someFunction.
Functions on your view model are slightly special because you can reference them by name, i.e., you can write submit: doSomething and don’t have to write submit: viewModel.doSomething (though technically that’s also valid).
Additional parameters
None
Notes
For information about how to pass additional parameters to your submit handler function, or how to control the this handle when invoking functions that aren’t on your view model, see the notes relating to the click binding. All the notes on that page apply to submit handlers too.
I am trying to store the inputs of the html form in a simple array.
I found some simple tutorials but my code is still not working, maybe I just can't see the fault.
This is how I made an array:
var person = [];
person[0] = $('#email').val();
person[1] = $('#password').val();
And this is my html, I have the span #demo, where I checked if there's a value in the array:
<input id="email" type="email" name="email" required="required"/><span id="errorfld"></span>
<input id="password" name="password1" type="password" required="required"/><span id="result"></span><span id="demo">text</span>
Then I have a function, which is called on focusout:
function demo(){
$('#demo').text(person[0]);
}
Do I have to search my fault somewhere else?
One way is to use $.serializeArray() to get all the values from the form.
Example
$('#form').on('submit', function(event) {
event.preventDefault();
var data = $(this).serializeArray();
$('#demo').text(data[0].value);
});
DEMO http://jsfiddle.net/7ysbd962/1/
If you just get the value when the page loads document.ready the input fields are still blank. You need to retrieve the values when you want to use them like this...
$(function(){
function updateDemo(){
var person = [];
person[0] = $('#email').val();
person[1] = $('#password').val();
$('#demo').text(JSON.stringify(person));
}
$('#email').on('blur',updateDemo);
$('#password').on('blur',updateDemo);
});
Here is an example
You could also use a different listener like keyup to update the value every time the key is pressed.
Another example
I have a ViewModel which accepts JSON to build observableArray() and also have a selected observable for storing the object when editing.
var ViewModel = function (data) {
var self = this;
self.list = ko.observableArray(data);
self.selected = ko.observable();
}
I'm showing the list in a table with edit button. On edit, the selected object goes into selected
self.edit = function (o) {
self.selected = ko.observable(o);
}
Next, I have a form which binds with the selected and displays all the properties.
<form>
<input type="text" data-bind="value: selected().Name">
</form>
The problem is that I want this form to be shown for adding an item and not only when the user clicks edit. But initially, the selected observable is undefined and throws error. Also, I want to push the data in selected to my observableArray when the user clicks on Add button.
What will be the best approach? Where can I put a custom binding so that this scenario works?
Update
My problem is similar this question.
But I can't implement the given solution to an observable
Fiddle implementing a part of problem and a suggested solution
<form data-bind="with: selected">
<input type="text" data-bind="value: Name">
</form>
This will not render the content of the form until a item is selected
To reuse form use a template binding
<form data-bind="template: { if: selected, data: selected, name: 'my-template' }">
</form>
Use a "blank" item in the selected variable to act as your "new item". Then, filling in the form for adding an item will fill in the values in the "blank" item.
Here are some snippets (partially based on your code and on another question)
Form:
<form data-bind="with: selected">
<input type="text" data-bind="value: Name">
</form>
ViewModel
var ViewModel = function (data) {
var self = this;
self.list = ko.observableArray(data);
self.selected = ko.observable(
{ name: "" });
}
Then, the "add" button for putting a new item into the data array can contain this:
// Add this item
self.list.push(self.selected());
// Reset the form to a new blank item
self.selected({ name: "" });
So when the form is loaded, there is an item in the selected variable - a blank item.
To avoid having to create a new blank model with all of the fields, you can use a variation on Ryan Niemeyer's answer here, using a valueWithInit binding for nonexistent fields. See his example jsFiddle.
Then, you can do this:
Form:
<form data-bind="with: selected">
<input type="text" data-bind="valueWithInit: Name">
</form>
ViewModel
var ViewModel = function (data) {
var self = this;
self.list = ko.observableArray(data);
self.selected = ko.observable({});
}
Seems like just simple javascript was the answer to the question.
I added one Cancel button and on click of it:
document.getElementById("form").reset();
This also cleared the selected observable.
Also, for initial form display I used $data with all the properties:
<form data-bind="with: selected" id="form">
<input type="text" data-bind="value: $data.Name">
</form>
No custom binding handlers were required!!
I have a reset function in angular to clear all the fields in a form. If I do something like:
reset
$scope.resetForm = function() {
$scope.someForm = {};
}
Everything works fine. But I want to use this function for multiple forms on the site. If I pass the form object in like:
reset
$scope.resetForm = function(form) {
$scope.form = {};
}
Then it won't work. Can someone explain to me why this would be happening?
You have 2 problems:
You're not accessing the passed in variable, still access the someForm of current scope.
When you pass parameter to the function, it's passed by reference. Even when you use form = {}, it does not work because it only changes the reference of the parameter, not the reference of the passed in someForm.
Try:
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
form.fieldA = null;
form.fieldB = null;
///more fields
}
Or
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
angular.copy({},form);
}
instead of:
$scope.resetForm = function(form) {
$scope.form = {};
}
In your plunk, I see that you're not separating the view from the model. You should do it for separation of concerns and to avoid problems that might happen when you clear all the fields (including DOM form object's fields).
<form name="form2" ng-controller="SecondController">
<label for="first_field">First Field</label>
<input ng-model="form2Model.first_field" />
<br />
<label for="second_field">Second Field</label>
<input ng-model="form2Model.second_field" />
<br />
Reset the form
</form>
http://plnkr.co/edit/x4JAeXra1bP4cQjIBld0?p=preview
You can also do:
form.fieldA = undefined;
It works great for radio buttons and checkboxes.
you can try this :
Deploy your function inside form button reset , in this way ...
<input type ="button" ng-click="Object.field1 = null; ObjectN.fieldN = null;" value="Reset" />