Function on form submit works only once [Angular] - javascript

I have made a search products app where I have form 3 fields from which I want to search the products. On submission the searchProducts() function is called which sends a get request to my api with request parameters it got from the form fields.
Problem - My form works only once. I can search only once and then I have to refresh the page to search again. Sometimes it works twice but not more than that. I do not know why.
I want to keep calling the searchProducts() function whenever the form is submitted. I want to work it again and again without refreshing the page as a user can search multiple times.
My searchProducts() function / Component -
export class SearchproductComponent implements OnInit {
isAuthenticated(){
return this.userService.isAuthenticated();
}
productSearchForm = this.fb.group({
productCode: [, []],
name: [, []],
brand: [, []],
priceLow: [,[]],
priceHigh: [, []]
})
get productCode(){
return this.productSearchForm.get('productCode');
}
get name(){
return this.productSearchForm.get('name');
}
get brand(){
return this.productSearchForm.get('brand');
}
constructor(private fb: FormBuilder, public productsService: ProductsService, public userService: UserserviceService) { }
ngOnInit(): void {
}
searchProducts(){
let name = this.productSearchForm.controls.name.value!
let brand = this.productSearchForm.controls.brand.value!
let productCode = this.productSearchForm.controls.productCode.value!
if (name && brand === null && productCode === null){
let response = this.productsService.getProductsByName(name)
console.log(response)
}
if (name && brand && productCode === null){
let response = this.productsService.getProductsByNameAndBrand(name, brand)
console.log(response)
console.log("Name and Brand Working");
}
if (name && brand && productCode){
let response = this.productsService.getProductsByNameAndBrandAndProductCode(name, brand, productCode)
console.log(response)
console.log("Name and Brand and Product Code Working")
}
It has more functions but you get the idea.
My searchProducts html file -
<div class="search-form">
<form (ngSubmit)="searchProducts()" [formGroup]="productSearchForm" name="productSearch" class="form-inline">
<div class="row">
<div class="col-4">
<div class="mb-3">
<label for="product-code" class="form-label">Product Code: </label>
<input type="text" class="form-control" id="product-code" name="product-code" formControlName="productCode">
</div>
</div>
<div class="col-4">
<div class="mb-3">
<label for="name" class="form-label">Name: </label>
<input type="text" class="form-control" id="name" name="name" formControlName="name">
</div>
</div>
<div class="col-4">
<div class="mb-3">
<label for="brand" class="form-label">Brand: </label>
<input type="text" class="form-control" id="brand" name="brand" formControlName="brand">
</div></div>
</div>
<div class="row">
<div class="col-2 mb-3">
<button type="submit" class="btn btn-primary mb-3">Search</button>
<button type="button" class="btn btn-warning" (click)="filterAnother()">Search Another</button>
</div>
<div class="col-10 mb-3" *ngIf="isAuthenticated();">
<div class="row">
<div class="col-2">
</div>
<div class="col-2">
<button type="button" class="btn btn-success mb-3" (click)="filterByPrice()">Filter by Price</button>
<button type="button" class="btn btn-primary" (click)="filterAnother()">Filter Another</button>
</div>
<div class="col-2 mu-2">
<label for="price-range" class="form-label price-range-label">Price Range: </label>
</div>
<div class="col-3">
<input type="text" class="form-control" id="price-range-low" name="price-low" formControlName="priceLow">
</div>
<div class="col-3">
<input type="text" class="form-control" id="price-range-high" name="price-high" formControlName="priceHigh">
</div>
</div>
</div>
</div>
</form>
</div>
I want searchProducts() to work again and again. It only works once.
My UI looks like this -
I tried adding another button search another to run function onclick but still does not work.

In your first if function, you are checking if all your inputs are null:
if (name && brand === null && productCode === null)
UPDATE:
You can do the following instead since you only search when there is a name typed in:
if (name !== null && brand === null && productCode === null)
So if you only search nulls, you won't get a response from your service I imagine. You're also doing the same check in the second if, just with a different logic:
if (name && brand && productCode === null)
UPDATE:
You can do the following instead since you are searching whenever there is a name & brand typed in:
if (name !== null && brand !== null && productCode === null)
Your third if function works since you are making sure that all of them exist, with this logic you should be able to search, but only if all 3 inputs have values, you can try in the link below:
if (name && brand && productCode)
I reproduced your code in StackBlitz and it looks like you need to improve your first 2 if statements logic so you can properly search when only one value (or 2) is being passed to angular service. Here is the StackBlitz link if you want to review it: https://stackblitz.com/edit/angular-ivy-ywlaqz?file=src/app/app.component.ts.

Related

Field 'mobile' expected a number but got ['2222222', '2222222']

This is Error showing
TypeError at /page
Field 'mobile' expected a number but got ['22222', '3333'].
Request Method: POST
Request URL: http://127.0.0.1:8000/page
Django Version: 4.1
Exception Type: TypeError
Exception Value:
Field 'mobile' expected a number but got ['22222', '3333'].
While Submitting Form This error occurs.
I am trying to submit form of same name twice simultaneously to same model
Views.py
def page(request):
if request.method == 'POST':
description = request.POST['description']
price = request.POST['price']
name = request.POST.getlist('name')
mobile = request.POST.getlist('mobile')
pay = bill(description=description,price=price)
pay.save()
mypayee = payee(billId=pay,name=name,mobile=mobile)
mypayee.save()
return render(request, 'split_app/page.html')
this model
from django.db import models
# Create your models here.
class bill(models.Model):
price = models.IntegerField()
description = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.description
class payee(models.Model):
billId = models.ForeignKey(bill,on_delete=models.CASCADE,related_name='persons')
name = models.CharField(max_length=50)
mobile = models.IntegerField()
this is image of HTML FORM generated using javascript
enter image description here
** This is how I am submitting data with form having same form twice of same name(name & mobile) **
HTML generate
<div class="container my-3">
<button type="button" class="btn btn-secondary">ADD NEW BILL</button>
<form action="/page" method="POST">
{% csrf_token %}
<div class="input-group mb-3">
<label for="discription" class="col-sm-2 col-form-label">DESCRIPTION:</label>
<div class="col-sm-2">
<input type="text" name="description" id="discription" placeholder="Bill For.." />
</div>
</div>
<div class="input-group mb-3">
<label for="price" class="col-sm-2 col-form-label">BILL PRICE:</label>
<div class="col-sm-2">
<input type="number" name="price" id="price" title="only numbers allowed"
placeholder="&#x20B9" />
</div>
</div>
<div class="mb-3 row">
<label for="person" class="col-sm-2 col-form-label">SPLIT IN:</label>
<div class="col-sm-10">
<button type="button" class="btn btn-info" onclick="increment()">+</button>
<button type="button" class="btn btn-info" id="payeesbtn">ADD PAYEE:</button>
<button type="button" class="btn btn-info" onclick="decrement()">-</button>
<div class="container my-3" id="addpayees"></div>
</div>
</div>
<button type="submit" class="btn btn-info">Save</button>
</form>
</div>
Javascript
let x = 1;
function increment() {
const div = document.createElement('div');
div.className = 'container my-3';
div.idName = 'x';
div.innerHTML = `<h5>payee ${x}</h5>
<table>
<tr>
<th>Name:</th>
<td><input type="text" name="name"></td>
</tr>
<tr>
<th>Mobile:</th>
<td><input type="number" name="mobile"></td>
</tr>
</table>
<input type="button" value="-" onclick="decrement(this)" />
<button type="button" class="btn btn-info" onclick="decrement(this)">-</button>`;
document.getElementById("addpayees").appendChild(div);
x++;
};
The payee.mobile field is defined as an IntegerField, but in your view function you are calling:
mobile = request.POST.getlist('mobile')
which produces a list of values. Then you do this:
mypayee = payee(billId=pay,name=name,mobile=mobile)
That is what the error tells you. You are trying to create a payee instance and assign a list to the integer field.
PS:
If you want to create two separate instances of payee with both those values ['22222', '3333'], you need to do something like:
mypayee1 = payee(billId=pay,name=int(name[0]),mobile=int(mobile[0]))
mypayee2 = payee(billId=pay,name=int(name[1]),mobile=int(mobile[1]))
But I am just guessing here.
PPS:
If the size of the name and mobile lists is dynamic, you could loop over them. You did not provide a lot of context, but I assume that those query parameters in the POST request will have the same number of items, i.e. the lists will be of the same size. Then you could do something like this:
def page(request):
...
names = request.POST.getlist('name')
mobiles = request.POST.getlist('mobile')
pay = bill(description=description,price=price)
pay.save()
for name, mobile in zip(names, mobiles):
mypayee = payee(billId=pay,name=name,mobile=int(mobile))
mypayee.save()
If you don't care about the pre_save and post_save signals, you could create them in bulk like this: (check the docs for caveats!)
def page(request):
...
names = request.POST.getlist('name')
mobiles = request.POST.getlist('mobile')
pay = bill(description=description,price=price)
pay.save()
payee.objects.bulk_create([
payee(billId=pay,name=name,mobile=int(mobile))
for name, mobile in zip(names, mobiles)
])
Either way, at this point I would strongly suggest wrapping the entire affair in a transaction to ensure data integrity.

Adding a second submit button to the form makes script unable to find element in the same form

I have a form with two buttons. To be able to arrange the buttons better I've placed them inside a div.
By adding a second button on the same form, one of the scripts returns: Uncaught TypeError: Cannot read properties of null (reading 'includes').
<form class="tab-pane active" id="input" name="input">
<!-- Input row -->
<span>Input 1 Address:</span>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="IP-Address"
aria-label="Input 1 IP Address" name="ip_1" id="ip_1"
onchange="ValidateIPaddressOnChange(this)">
<span class="input-group-text">:</span>
<input type="text" class="form-control" placeholder="Port"
aria-label="Input 1 Port" name="port_1" id="port_1" pattern="\d*"
maxlength="5">
</div>
<!-- Submit Buttons -->
<div class="buttons d-flex justify-content-between">
<button class="btn btn-success" type="submit" name="save_io">Save</button>
<button class="btn btn-danger" type="submit" name="reset_io">Reset</button>
</div>
</form>
Script:
function ValidateIPaddress(form) {
console.log(form.elements[0].ariaLabel);
for (let i = 0; i < form.elements.length - 1; i++) {
// Select only the ip Address inputs
if (form.elements[i].ariaLabel.includes("Address")) {
if (form.elements[i].ariaLabel.includes("Network") && form.elements[i].placeholder != 'DHCP IP' &&
!form.elements[i].value.match(ipformat)) {
alert(`You have entered an invalid ${form.elements[i].ariaLabel}!`);
form.elements[i].focus();
return false;
} else if (form.elements[i].value.length > 0 && !form.elements[i].value.match(ipformat)) {
alert(`You have entered an invalid ${form.elements[i].ariaLabel}!`);
form.elements[i].focus();
return false;
}
}
}
return true;
}
let input_form = document.getElementById("input");
input_form.addEventListener("submit", function (e) {
e.preventDefault();
if (ValidateIPaddress(input_form)) {
saveSettings(input_form, "input/post");
input_form.reset();
}
});
What is strange is that console.log(form.elements[0].ariaLabel); returns Input 1 IP Address, which is correct, so why does:
if (form.elements[i].ariaLabel.includes("Address")) return
Uncaught TypeError: Cannot read properties of null (reading 'includes') ?

Javascript: Trying to access window.variable but it stays undefined even after initialising

I have initialized 4 global variables in function 1 and have also assigned values to the functions. When I try to access the variables in the next function, only the first variable is accessible. All others are undefined.
Function1 is called when a user fills up basic form information. He is then redirected to an advanced form. After filling up both the forms, the data is then stored in a database.
Kindly provide some solution.
<!-- language: lang-js -->
`````
<!--'Postspace.js' File-->
function function1() {
window.name = $scope.data.name;
// window.email = 'c#g.com';
window.varemail = $scope.data.email;
window.varmobile = $scope.data.mobile;
window.varlocation = $scope.data.location;
console.log(window.name);
console.log(window.varemail);
console.log(window.varmobile);
console.log(window.varlocation);
}
function function2() {
console.log(window.name);
console.log(window.varemail);
console.log(window.varmobile);
console.log(window.varlocation);
'name': window.name,
'email': window.varemail,
'mobile': window.varmobile,
'location': window.varlocation,
'working_space': $scope.workingSpace.category,
'no_of_persons': $scope.noOfPerson,
'joining_date': $scope.startDate,
'working_hours': workingHours,
'period': $scope.period,
'multipleDays': $scope.multipleDays,
}
>
> form.blade.php file
> I am taking the values in the php file in this format: This is an example of
> how I am accepting the name and the mobile field. `
````
<div class="col-lg-10 col-md-10 form-group" ng-class="{'has-error': LoginForm.fullEmail.$invalid && LoginForm.fullEmail.$touched}">
<p class="form-label ">Your Email</p>
<div class="row ">
<div class="col-lg-8 col-md-8"> <input type="email" ng-model="data.email" name="fullEmail" class="form-control " required placeholder="EMAIL" ng-model-options="{debounce: 200}"></div>
</div>
</div>
<div class="col-md-10 form-group" ng-class="{'has-error': LoginForm.fullmobile.$invalid && LoginForm.fullmobile.$touched}">
<p class="form-label">Your Mobile</p>
<div class="row">
<div class="col-md-8"><input type="text" ng-model="data.mobile" name="fullmobile" class=" form-control" required placeholder="MOBILE" ng-pattern="/^[6-9]{1}[0-9]{9}$/"></div>
</div>
</div>
````
Can you show the code that holds the values for $scope.data object...

Sweetalert PoP-up message when fields are field is not working

I had a question about Sweetalert a week ago. Then I got an answer which helped me, but unfortunately, it is still not working. I wanted a Sweetalert pop-up message (success) when the user hits the submit button, but only if the fields are filled. I do not know what the problem is. Currently, nothing happens when the user hits the button.
Here is my code:
function Sweetalert1(){
var name = document.getElementById("name").value;
var message = document.getElementById("message").value;
var email = document.getElementById("email").value;
if (name != " " && message != " " && email != " "){
Swal.fire(
'Köszönjük!',
'Megkaptuk a leveledet és hamarosan válaszolunk!',
'success',
)}
}
And the part of the HTML:
<form role="form" id="contactForm" action="contact.php" method="post">
<div class="control-group">
<div class="form-group floating-label-form-group controls mb-0 pb-2">
<label>Név</label>
<input class="form-control" id="name" name="name" type="text" placeholder="Név" required="required" data-validation-required-message="Kérlek add meg a neved!">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="control-group">
<div class="form-group floating-label-form-group controls mb-0 pb-2">
<label>Email Cím</label>
<input class="form-control" id="email" type="email" name="email" placeholder="Email" required="required" data-validation-required-message="Kérlek add meg az Email címed!">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="control-group">
<div class="form-group floating-label-form-group controls mb-0 pb-2">
<label>Üzenet</label>
<textarea class="form-control" id="message" rows="5" placeholder="Üzenet" name="message" required data-validation-required-message="Kérlek írd be az üzeneted!"></textarea>
<p class="help-block text-danger"></p>
</div>
</div>
<div id="success"></div>
<div class="form-group">
<button name="submit" type="submit" class="btn" id="sendMessageButton">Küldés</button>
</div>
</form>
I can't see where the button was fired
On this line,
<button name="submit" type="submit" class="btn" id="sendMessageButton">Küldés</button>
You have at least two options to fire the button
1st
You can change the line to this
<button name="submit" type="submit" class="btn" id="sendMessageButton" onclick="Sweetalert1()">Küldés</button>
2nd
You can add this to your javascript section
$("#sendMessageButton").click(function(){
Sweetalert1();
});
3rd
You can use the form's on-submit event
$("form").submit(function(){
Sweetalert1();
});
When this is done, modify your condition to
if (name !== "" && message !== "" && email !== "")
OR
if (name.trim() && message.trim() && email.trim())
your condition is not right, try doing this:
if (name && message && email)
{
// Code
}
An empty field isn't equal to a space (" "), it is equal to an empty string (""). So, you need to check if the fields equal an empty string, not a field with a space:
if (name != "" && message != "" && email != "") {
// code...
}
However, if you want to treat fields which have no text in them (and just spaces) as invalid as well, you can add the .trim() method to your name, message and email variables. By using trim you can turn inputs such as
" " into "", which will then be treated as an invalid input:
if (name.trim() != "" && message.trim() != "" && email.trim() != "") {
// code...
}
As an empty string is considered falsey (ie "" == false) you don't need to check whether you're input equals an empty string and instead can just check if x.trim() evaluates to true like so:
if (name.trim() && message.trim() && email.trim()) {
// code...
}

Firebase Chat change reference with javascript

I am trying out how to incorporate firebase with angular in such a way that the user is able to change the "Channel" of the chat via selecting from a dropdownlist.
This is the code that I have at the moment:
Note: The channel attribute is defined in another portion of code, and the entire page is loaded only once.
app.controller('mychat', function($scope, $firebaseArray) {
var d = new Date();
var today = d.getDate()+d.getMonth()+d.getYear();
var txt = document.getElementById('txtFBMsgs'); //store id of textbox
//Query
var ref = firebase.database().ref().child(channel)
$scope.fbmessages = $firebaseArray(ref);
$scope.send = function() {
if (txt.value != ""){ //check if textbox contains any message
$scope.fbmessages.$add({
sender: sender,
message: $scope.messageText,
date: Date.now()
})
txt.value = ""; //reset value of textbox
}
}
})
and here is my html portion:
<div class="card mb-1 col-md-3" ng-controller="mychat" id="myDiv">
<div class="card-body" style="overflow-x: hidden; overflow-y:scroll; min-height:60vh; max-height:64vh;">
<div>
<p ng-repeat="m in fbmessages"> {{m.date | date:'short'}} - {{m.sender}}: <br> {{m.message}}</p>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-9">
<input type="text" id = "txtFBMsgs" class="form-control" placeholder="Message here..." ng-model="messageText" onkeydown = "if (event.keyCode == 13) document.getElementById('sendBtn').click()">
</div>
<div class="form-group col-md-3">
<button type="submit" class="btn btn-primary btn-block" id="sendBtn" ng-click="send()">Send</button>
</div>
</div>
basically, it is a div that displays the chat messages, and an input box which is able to send the message to firebase.
Can I change the 'Channel' dynamically via javascript, such as on an onchange in a DDL?

Categories

Resources