Hide field based on checkbox using javascript in odoo 12 - javascript

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;">

Related

click event on button is disabling the default behavior of html required

<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.

How to make it mandatory to select a value in Autoselect while using template

Scenario : we have a Kendo UI template. When a user tries to type atleast 2 charters data is populated in Autocomplete widget. I cannot use combobox as return data may be huge and combobox freezes. I want to force user to select a option from Auto complete dropdown and if nothing is returned from autocomplete or if user not select a data I want to clear the text field.The issue with my code is that everytime it clears the first row in the template and not the relevant one where data is not selected.
Template declaration
<script id="newTestTemplate" type="text/x-kendo-template">
<div id="testRec">
<input id="pSearchId" class="pSearch"
data-role="autocomplete"
data-placeholder="Select from dropdown"
data-text-field="name"
type="text"
data-bind="source: pSearchDS, value: name, events: {select: pSelected,open : pOpen,close : pClose}"
data-min-length="2"
data-highlight-first="true" maxlength="160" />
<input id="pDesc" data-role="textbox" placeholder="Description" class="k-textbox part-input" data-bind="value: description/> </div>
Javascript:
pOpen = function (e) {
valid = false;
}
pClose = function (e) {
if (!valid) {
$(e.sender).closest(".pSearch").val("");
$("#pDesc").val(''); //tried this way too
}
}
pSelected = function (e) {
valid = true;
}
Please suggest . If there is anyother way to force implement selection then let me know that too.
You can try the following on Autocomplete blur check if the user selected any value if not clear the values
$("#pSearchId").blur(function(){
if (!valid) {
alert("User not selected any value");
$("#pSearchId").val('');
$("#pDesc").val('');
}
});
For this I ended up putting validation on the click even to check if text box have a value.

How to add multiple input field inside a div dynamically using JavaScript/jQuery?

I need to create some multiple input field dynamically on onkeypress event using JavaScript/jQuery.
I have one text-box,when user is entering any key on that text area two input field and second text-box is opening. When user will enter any key on second text box again another two input field and third text-box will open and so on. There is also a cross button is creating to close each individual set of text-box. In my current code I doing this putting all field static as user may create many numbers of input field so that I want to create those in dynamically with different name and id.
My code is in this Plunkr.
EDIT: Misunderstood question, answer below
This can easily be done if you have a specific field in which to create the input fields. For example, I will load input fields into document.body
Everytime you call newinput() an input field is created in parent who's id starts at input0 and increments each time
var id = 0;
var newinput = function() {
var parent = document.body
var field = document.createElement("input")
field.className = "myclassname"
field.style = "display:block;"
field.id = "input" + id;
parent.appendChild(field);
id += 1;
}
<body>
<div>Click plus to add input</div>
<button type="button" name="button" onclick="newinput()">+</button>
</body>
In your case, it looks like you want to add a group, you can do this:
var fieldgroup = document.querySelector(".questionshowp .form-group").cloneNode(true); // (1)
var addinput = function(){
var parent = this.parentNode.parentNode.parentNode; // (2)
var n = parent.querySelectorAll(".form-control").length
var f = fieldgroup.cloneNode(true);
f.children[0].id = "question"+n // (3)
f.querySelector(".secondsec").querySelector("button.btn-success").onclick = addinput // (4)
parent.insertBefore(f,parent.querySelector(".clear")); // (5)
}
Create a copy of a field-group to be used as a template
Get the container of input fields
Set the input field id with regard to total number of form-groups in parent
Make sure template applies addinput() to button
Insert input form before end of parent form
The easiest way apply this function to all + buttons is with JQuery
$("button.btn-sm.btn-success").on("click", addinput)
This would need to be located at the bottom of your html file, and below addinput() definition
EDIT: Real Answer
Turns out I wrote all that and just realized I misunderstood your question.
Still we can use the same principle to do what I believe you are asking
master = document.querySelector(".aquestionpart"); // (1)
form = document.querySelector(".questionparts"); // (2)
function show(){
var f = form.cloneNode(true);
var n = master.querySelectorAll(".questionparts").length;
f.id = "questionparts"+(n+1); // (3)
f.querySelector("#questions").onkeypress = show; // (4)
this.parentElement.parentElement.querySelector("#questionparts"+ n + " > .questionshowp").style ="display:block;"; // (5)
this.onkeypress = undefined; // (6)
master.insertBefore(f,master.children[master.children.length-1]) // (7)
}
form.querySelector("#questions").onkeypress = show; // (8)
form = form.cloneNode(true); // (9)
Get poll container
Get poll question form to use as template
Set new poll question form id with respect to number of others
Set show function to new poll question
Show multiple choice
Make sure subsequent keypresses dont create more questions
Insert question before .clear
sets up first question to show
creates copy of fresh question to use as template
With this your current scripts.js is unnecessary, and .aquestionpart must look like this for proper formatting
<div class="aquestionpart">
<div class="questionparts" id="questionparts1">...</div>
<div class="clear"></div>
</div>
From within .questionparts be sure to remove onkeypress="show();" from input. It should look like this.
<input name="questions" id="questions" class="form-control" placeholder="Questions" value="" type="text">
And finally an interesting note is that both of the scripts I've provided can be used together! (With some slight modifications)
//Author: Shane Mendez
var fieldgroup = document.querySelector(".questionshowp .form-group").cloneNode(true);
var addinput = function(){
var parent = this.parentNode.parentNode.parentNode;
var n = parent.querySelectorAll(".form-control").length
var f = fieldgroup.cloneNode(true);
f.children[0].id = "question"+n
f.querySelector(".secondsec").querySelector("button.btn-success").onclick = addinput
console.log(parent)
parent.insertBefore(f,parent.children[parent.children.length-1]);
}
master = document.querySelector(".aquestionpart");
form = document.querySelector(".questionparts");
function show(){
var f = form.cloneNode(true);
var n = master.querySelectorAll(".questionparts").length;
f.id = "questionparts"+(n+1);
f.querySelector("#questions").onkeypress = show;
console.log(this)
this.parentElement.parentElement.querySelector("#questionparts"+ n + " > .questionshowp").style ="display:block;";
this.onkeypress = undefined;
master.insertBefore(f,master.children[master.children.length-1])
$(f.querySelectorAll("button.btn-sm.btn-success")).on("click", addinput)
}
form.querySelector("#questions").onkeypress = show;
form = form.cloneNode(true);
$("button.btn-sm.btn-success").on("click", addinput)
If you put this in your scripts.js file and put that at the bottom of your body tag, then the only thing left is the - buttons.
You can use this Press to add multiple input field inside a div dynamically using jQuery. Here you only need to call the function that takes two parameter HTMLElement and config like:
$(".addInput").click(function() {
build_inputs($(this), config);
});
In the config you can add numbers of inputs form config like:
let config = {
title: "Slides",
forms: [
{
type: "text",
name: "name",
class: "form-control mb-2",
placeholder: "Enter Data..."
},
{
type: "file",
name: "image",
class: "btn btn-light btn-sm mb-2 btn-block"
},
{
type: "number",
name: "mobile",
class: "form-control mb-2",
placeholder: "Enter Data..."
}
],
exportTo:$('#getData')
};

Javascript Checkbox Required Funcion Only for 1 Form

I'm trying to use the following JS that I found around here and since I have multiple forms on a page I would like to customize the function to only work with specific form ID.
In my case <form id="car" ...
// required checkboxes
var requiredCheckboxes = $(':checkbox[required]');
requiredCheckboxes.change(function(){
if(requiredCheckboxes.is(':checked')) {
requiredCheckboxes.removeAttr('required');
}
else {
requiredCheckboxes.attr('required', 'required');
}
});
You have to modify your query as follows in order to select only the checkboxes from your form:
var requiredCheckboxes = $("#car").find(':checkbox[required]');

copy form to Backbone.js model

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);
}

Categories

Resources