Angular check if Button was clicked - javascript

I want to display a changed text value only if a Button has been clicked. The text value depends on an input field, and is dynamically bound to the input value of the text field with [(NgModel)]="textValue"...
I first enter some ID number into the input box and it directly changes my text. But I only want the text with the "ID-value" to change after I clicked the button, and called the new charts data with my function "getChartsData()".
This is how my html looks like:
<input [(ngModel)]="monatConst" placeholder="Demonstrator-ID">
<button class="btn btn-danger float-xl-right mt-1"
(click) = "getChartsData()"> Call HTTP Request
</button>
<br>
<div *ngIf="monatConst">Chart für Demonstrator mit ID: {{monatConst}} </div><br>
<ngx-charts-bar-vertical
[view]="view"
[scheme]="colorScheme"
[results]="dataArray"
[gradient]="gradient"
[xAxis]="showXAxis"
[yAxis]="showYAxis"
[legend]="showLegend"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[xAxisLabel]="xAxisLabel"
[yAxisLabel]="yAxisLabel">
</ngx-charts-bar-vertical>
How can I best realize that the text with the ID field is only changed after clicking the button, and calling the new charts data? For the moment, I bound the ID variable two way with ngModel and put it directly into the text field with data binding {{..}}

I found a much simpler solution, it was pretty stupid from me ;) :
<div *ngIf="dataArray?.length>0; else noChartBlock">
Chart für Demonstrator mit ID: {{monatConst}}
<ngx-charts-bar-vertical
[view]="view"
[scheme]="colorScheme"
[results]="dataArray"
[gradient]="gradient"
[xAxis]="showXAxis"
[yAxis]="showYAxis"
[legend]="showLegend"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[xAxisLabel]="xAxisLabel"
[yAxisLabel]="yAxisLabel">
</ngx-charts-bar-vertical>
</div>
<ng-template #noChartBlock>
<b>There is no data for Demonstrator with ID: {{monatConst}} !</b>
</ng-template>
I just packed my Text inside the ngIf selector so that it displays the text if something was found, otherwise it goes to the else template block... ;P

.html
<input [(ngModel)]="monatConst" placeholder="Demonstrator-ID">
<button class="btn btn-danger float-xl-right mt-1"
(click) = "getChartsData();setText(monatConst)"> Call HTTP Request
</button>
<br>
<div *ngIf="Demonstrator_ID">Chart für Demonstrator mit ID: {{Demonstrator_ID}} </div><br>
.ts
monatConst:any;
Demonstrator_ID: any;
setText(text){
this.Demonstrator_ID=text;
}

Related

Pre-populate current value of WTForms field in order to edit it

I have a form inside a modal that I use to edit a review on an item (a perfume). A perfume can have multiple reviews, and the reviews live in an array of nested documents, each one with its own _id.
I'm editing each particular review (in case an user wants to edit their review on the perfume once it's been submitted) by submitting the EditReviewForm to this edit_review route:
#reviews.route("/review", methods=["GET", "POST"])
#login_required
def edit_review():
form = EditReviewForm()
review_id = request.form.get("review_id")
perfume_id = request.form.get("perfume_id")
if form.validate_on_submit():
mongo.db.perfumes.update(
{"_id": ObjectId(perfume_id), <I edit my review here> })
return redirect(url_for("perfumes.perfume", perfume_id=perfume_id))
return redirect(url_for("perfumes.perfume", perfume_id=perfume_id))
And this route redirects to my perfume route, which shows the perfume and all the reviews it contains.
This is the perfume route:
#perfumes.route("/perfume/<perfume_id>", methods=["GET"])
def perfume(perfume_id):
current_perfume = mongo.db.perfumes.find_one({"_id": ObjectId(perfume_id)})
add_review_form = AddReviewForm()
edit_review_form = EditReviewForm()
cur = mongo.db.perfumes.aggregate(etc)
edit_review_form.review.data = current_perfume['reviews'][0]['review_content']
return render_template(
"pages/perfume.html",
title="Perfumes",
cursor=cur,
perfume=current_perfume,
add_review_form=add_review_form,
edit_review_form=edit_review_form
)
My issue
To find a way to get the review _id in that process and have it in my perfume route, so I can pre-populate my EditReviewForm with the current value. Otherwise the form looks empty to the user editing their review.
By hardcoding an index (index [0] in this case):
edit_review_form.review.data = current_perfume['reviews'][0]['review_content']
I am indeed displaying current values, but of course the same value for all reviews, as the reviews are in a loop in the template, and I need to get the value each review_id has.
Is there a way to do this, before I give up with the idea of allowing users to edit their reviews? :D
Please do let me know if my question is clear or if there's more information needed.
Thanks so much in advance!!
UPDATE 2:
Trying to reduce further my current template situation to make it clearer:
The modal with the review is fired from perfume-reviews.html, from this button:
<div class="card-header">
<button type="button" class="btn edit-review" data-perfume_id="{{perfume['_id']}}" data-review_id="{{review['_id']}}" data-toggle="modal" data-target="#editReviewPerfumeModal" id="editFormButton">Edit</button>
</div>
And that opens the modal where my form with the review is (the field in question is a textarea currently displaying a WYSIWYG from CKEditor:
<div class="modal-body">
<form method=POST action="{{ url_for('reviews.edit_review') }}" id="form-edit-review">
<div class="form-group" id="reviewContent">
{{ edit_review_form.review(class="form-control ckeditor", placeholder="Review")}}
</div>
</form>
</div>
Currently this isn't working:
$(document).on("click", "#editFormButton", function (e) {
var reviewText = $(this)
.parents(div.card.container)
.siblings("div#reviewContent")
.children()
.text();
$("input#editReviewContent").val(reviewText);
});
and throws a ReferenceError: div is not defined.
Where am I failing here? (Perhaps in more than one place?)
UPDATE 3:
this is where the button opens the modal, and underneath it's where the review content displays:
<div class="card container">
<div class="row">
<div class="card-header col-9">
<h5>{{review['reviewer'] }} said on {{ review.date_reviewed.strftime('%d-%m-%Y') }}</h5>
</div>
<div class="card-header col-3">
<button type="button" class="btn btn-success btn-sm mt-2 edit-review float-right ml-2" data-perfume_id="{{perfume['_id']}}" data-review_id="{{review['_id']}}" data-toggle="modal" data-target="#editReviewPerfumeModal" id="editFormButton">Edit</button>
</div>
</div>
<div class="p-3 row">
<div class=" col-10" id="reviewContent">
<li>{{ review['review_content'] | safe }}</li>
</div>
</div>
</div>
You can do this with jQuery as when you open the form, the form will automatically show the review content in there. It will be done by manipulating the dom.
Also, add an id to your edit button, in this example, I have given it an id "editFormButton".
Similarly, add an id to the div in which review content lies so that it is easier to select, I have given it an id "reviewContent"
Similarly, add an id to edit_review_form.review like this edit_review_form.review(id='editReviewContent')
<script>
$(document).on("click", "#editFormButton", function (e) {
var reviewText = $(this)
.parents("div.row")
.siblings("div.p-3.row")
.children("div#reviewContent")
.children()
.text();
$("input#editReviewContent").val(reviewText);
});
</script>
Don't forget to include jQuery.
Also, you can do it with pure javascript. You can easily search the above equivalents on google. This article is a good start!

How to update the input box date through ngModel in ngb-Datepicker?

I have an input box which uses ngb-datepicker for the date. When I am trying to get the value from date picker through ngModel, it is working. But it is not working when I am trying to update ngModel from the function, input box is not getting updated. Please find the snippet below just for reference.
working stackblitz link is - Working Link
Selecting the date from calendar first and then the next day is updating the value in modal but not in the input box.
<!-- typescript code -->
import {Component} from '#angular/core';
#Component({
selector: 'ngbd-datepicker-popup',
templateUrl: './datepicker-popup.html'
})
export class NgbdDatepickerPopup {
model ;
nextDay() {
this.model.day = this.model.day +1 ;
}
}
<!-- Html code -->
<form class="form-inline">
<div class="form-group">
<div class="input-group">
<input class="form-control" placeholder="yyyy-mm-dd"
name="dp" [(ngModel)]="model" ngbDatepicker #d="ngbDatepicker">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar" (click)="d.toggle()" type="button"></button>
</div>
</div>
</div>
</form>
<hr/>
<button class="btn btn-sm btn-outline-primary mr-2" (click)="nextDay()">Next Day</button>
<pre>Model: {{ model | json }}</pre>
As I said in the comment, there is some point in the component tree where has been set ChangeDetectionStrategy.OnPush. In this case, inside the ngb-datepicker source code, you can see that this strategy is used.
This means that the change detection algorithm will be executed in its lighter version, and it will trigger an update only if the variable reference is changed.
So, in order to trigger change detection, you have to assign a new object to the variable rather than changing the property in place.
You can take advantage of the spread operator to have a more elegant code:
this.model = {...this.model, day: this.model.day+1};
Or just create a new object in the old style way:
this.model = Object.assign({}, this.model, {day: this.model.day+1});

Run js when pop over text input is loaded

Wanted to have cleave.js to format text input on the fly.
I have 2 text inputs
HTML text input and
also a pop over text input whenever search icon is clicked.
The issue is on popover text input where cleave text formating is not
working.
I believe it could be related to the element hasn't exist somehow? I have try to listen to listener but no luck so far. .on('shown.bs.popover)
My code as as per below
https://jsfiddle.net/fairul82/y3kf92oq/
Libraries used : cleave,js , bootstrap popover , jquery
HTML
<div class="container">
<h3>Bootstrap 3 Popover HTML Example</h3>
<input type="text" class="input-element"><br>
<ul class="list-unstyled">
<li><a data-placement="bottom" data-toggle="popover" data-
container="body" data-placement="left" type="button" data-html="true"
href="#" id="login"><span class="glyphicon glyphicon-search" style="margin:3px 0 0 0"></span></a></li>
<div id="popover-content" class="hide">
<form class="form-inline" role="form">
<div class="form-group">
<h1>
My Content
</h1>
<input type="text" class="input-element"><br>
</div>
</form>
</div>
//JS
$("[data-toggle=popover]").popover({
html: true,
content: function() {
return $('#popover-content').html();
}
});
$("[data-toggle=popover]").on('shown.bs.popover', function() {
// alert('called back');
const cleave = new Cleave('.input-element', {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
});
});
const cleave = new Cleave('.input-element', {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
});
Here is solution https://jsfiddle.net/ztkv8w60/19/
According to authority document https://github.com/nosir/cleave.js, it has a note .input-element here is a unique DOM element. If you want to apply Cleave for multiple elements, you need to give different css selectors and apply to each of them.
It is tricky question, because the bootstrap popover creates the same element as your specific div when the icon gets a click. Therefore there are two the same element, you have to point it out which element is in a popover.

Loading animation is not working

So I am using the following jQuery snippet to make a loading animation run (created in CSS) when a file is selected in an input field and then an upload button is clicked.
The form has 3 input fields with 3 upload buttons and is quite flexible. For e.g if a user selects a file in the first input field but clicks on the second upload button the loading animation should run around the first input field only. Another example is that if a user selects a file in the first input field and the second input field but clicks on the third upload button then the loading animation should run in the first and second input fields only.
$(document).ready(function() {
$(document).on("click", ".UploadBtn", function() {
$(".p").each(function(file) {
if ($(this).val()) {
$(this).next(".loader").show();
$(this).next(".loader").find(".spinner").show();
$(this).next(".loader").find(".UploadBtn").hide();
}
});
});
});
The code fails to run in the IF statement function. If i change the code (mentioned below) it will make the animation run but it ends up making the loading animation run in all 3 selection fields even if only one file was selected. This is not what is required but does tell me that the part of the code which has the IF statement breaks down in the code above;
$(document).ready(function() {
$(document).on("click", ".UploadBtn", function() {
$(".p").each(function(file) {
if ($(this).val()) {
$(".loader").show();
$(".spinner").show();
$(".UploadBtn").hide();
}
})
});
});
I am a beginner level coder and I have spent hours trying to fix this issue but nothing worked. Your help is greatly appreciated!
HTML snippet added as per recommendation
(It also has some Python code which was done by my friend) form.photo1, 2 and 3 have class = "p" ;
<div class="mtl mbl">
{{ form.photo1 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
<div class="mtl mbl">
{{ form.photo2 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
<div class="mtl mbl">
{{ form.photo3 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">

Prevent click on form button while file is loading

I am using the following snippet which allows a person to upload up to 3 files with a single upload button. While the file is being uploaded an animation runs in place of the upload button.
My requirement is that I need to prevent the user from clicking on any of the input field buttons while the file is getting uploaded. I do not wan't to use the hide() function for this. Is there a way in jQuery to stop the input field buttons from getting clicked on while the file is getting uploaded/the loading animation is running.
Recently started to use jQuery so still a beginner and hence would love to use a simple solution for this. Thanks!
<script type="text/javascript">
$(document).ready(function() {
$(document).on("click", ".UploadBtn", function(event) {
$(".p").each(function(file) {
if ($(this).val()) {
$(".loader").show();
$(".spinner").show();
$(".UploadBtn").hide();
}
})
});
});
</script>
My HTML code is below. The "p" class is used for {{ form.photo1 }}, {{ form.photo2 }} & {{ form.photo3 }} ;
<div class="mtl mbl">
{{ form.photo1 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
<div class="mtl mbl">
{{ form.photo2 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
<div class="mtl mbl">
{{ form.photo3 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
When the upload button, which the red button is pointing at, is
clicked an animation starts to run in its place while the file is
getting uploaded. During this I want to prevent anyone from clicking
on the choose file (), the blue arrow is pointing at it.
Try using prop to disable upload buttons
$(document).ready(function() {
$(document).on("click", ".UploadBtn", function(event) {
$(".p").each(function(file) {
if ($(this).val()) {
$(".loader").show();
$(".spinner").show();
$(".UploadBtn").prop("disabled", "true");
}
})
});
});
In jQuery 1.6+ you can dynamically add the atrribute attr='disabled' or attr='readonly' to your input field until you confirm that your files are loaded:
// put this within the code that checks if the files are still loading
$(".UploadBtn").prop('disabled', true);
// within the code that checks if the files have successfully loaded, make sure to use the following
$(".UploadBtn").prop('disabled', false);
Also take a quick look at what prop does in this detailed answer.

Categories

Resources