Reload part of HTML without refreshing page? - javascript

When clicking on an button icon:
<a onclick="updateFav({{v.video_id}}, {{v.favorite}});" ><span class="myicons {% if v.favorite == 1 %} heart_active{% else %} heart {% endif %} "></span></a>
I'm using this to change data in my sql database
function updateFav(video_id, favorite) {
$.ajax({
type: "POST",
url: '{{baseurl}}/fav.php',
data:{id:video_id, fav:favorite},
});
}
Depending on database data (0 or 1) heart icon will be gray or red. Clicking on icon works and after refreshing page the changes are visible.
How can I refresh a certain html element? A div for example.
Basically: Have the same effect as the 'star' favorite button on this page (stackoverflow).

To reload a part of a page without refreshing the whole page simply use an ajax request to fetch new data and add it to the div or any element you want see the code below for an example:
$.ajax({
type: "GET",
url: 'getnewData.php',
success:function(response){
$('#myElement').html(response);
},
});
What we did here is we issued an ajax request in which we requested data from getnewData.php and placed the data (which came to us in the response variable) and then we placed the data in the div with an id = myElement

You can go all the way and use a reactive framework or just create a function to update the current element after updateing the database.
When selecting with jQuery $('') or with plain js document.querySelector(), you get a living reference to the DOM element. So you can add/toggle/remove an "active class" to it to styled it as filled with css.
Tricky part here is that you have to keep consistency between the view and the model with your own code. Reactive frameworks or two-way data binding do it for you.

Related

Dynamically loaded JS needs to be clickable just like it's in the html

My page fires off an ajax query, where the MySQL Db is queried and the results are returned. (all successful).
Those results are formatted for output as a shopping gallery/catalogue and also as an accordion filter menu. So I can filter the shopping catalogue display. eg say I want to see only items that are red.
All is working so far.
My problem is with the filter accordion menu - dynamically created in js.
When I click on any selectable item in the tab-content, nothing happens. This means the parameter that should be sent, isn't being sent.
If I hard code the accordion filter or even load it with my server-side language, into the html directly, the filtering does send off the parameter and so the shopping catalogue is adjusted accordingly but, in that scenario, I am unable to dynamically change the filter menu.
I think the code I shall post below is the relevant code that recognises changes in the originally loaded content and fires off the ajax but (I think) it doesn't understand any changes to textboxes in the dynamically loaded content.
Please help me to understand what I need to add that will make dynamically loaded content fire-off to the ajax calls.
var $checkboxes = $("input:checkbox");
function update_nav_filter(opts) {
$.ajax({
type: "POST",
url: "/php-queries/product-filter-query.php",
dataType: 'json',
cache: false,
data: {
filterOpts: opts
},
success: function(records) {
//console.log(records);
//alert('SUCCESS!');
// alert(records);
$('#filters_div').html(makeFilter(records));
}
});
}
$checkboxes.on("change", function() {
//alert('there is a change is checkbox status'); // working on page load but not when any checkbox is clicked-on
var opts = getCatalogueFilterOptions();
updateCatalogue(opts);
update_nav_filter(opts);
});
$checkboxes.trigger("change");
Any help greatly appreciated.
I have created an event listener.
Following page-load, I select an item in the JS generated nav filter. eg pedal_bins in the sub_category section. I am then shown a display of pedal_bins. :)
Then I select 'kettles', another sub_category but I can only see the last sub_category that I click on. The pedal_bins disappear.
How best can I build and remove items with a single click? Store in a session parameter and then
a. remove the latest click if it matches whats in the session
b. add the latest click if its not already in the session
Then submit whatever the array is at that stage?
Or, is there a better way to run this?
Here's the listeneer
enter code here
document.getElementById("filtering_div").addEventListener("click",function(e) {
// e.target was the clicked element
if (e.target && e.target.matches("input")) {
var parameter = e.target.id;
//console.log("Anchor element", parameter , " was clicked" );
var opts = getCatalogueFilterOptions(parameter);
console.log(opts);
// update_nav_filter(opts);
updateCatalogue(opts);
}
});
You have a "delegation" problem. When you create a dynamic element, in order to be able to act on the newly created element, you have to reference it as a child element that was originally loaded with the DOM.
For example, if you have an element called <div id="top"></div> and you create a dynamic element, let's say <button id="test">Click</button> in there, you'll have to refer to that div when adding an event listener.
$("#top").on('click', '#test', function(){
//event related code goes here.
});
Here is a fiddle I created that explains the whole thing with some examples.
If you have any questions about it, please let me know.

Getting the value of an input field, which gets dynamically placed (not via js) onclick

I spent a few hours searching and trying stuff out, but I can't get my ajax form submit working. (I'm also really not a front-end person, so sorry if I mess up my explanation)
I have a site that dynamically inserts HTML content (through JSP, not javascript). I have a simple form with a submit button inside that inserted html. This is the piece of html I have:
<tr>
<td>Change stock by:</td>
<td>
<div id="quantityinput" class="field has-addons">
<div class="control"> <input class="input" type="text" id="mutation" placeholder="0">
</div>
update
</div>
</td>
</tr>
I managed to link the button to the right ajax-function, like this:
(.editor__product is the direct parent of the form, but there is a bunch of non-form information there)
$(".editor__product").on("click", "#quantityConfirm", function ($) {
$.ajax({
method: "POST",
url: '/bullet-journal/mutateitem',
data: {
product_id: product_id,
product_mutate: product_mutate
}
})
.done(function (html) {
$('#main').load(document.URL + ' #main');
$(".editor__product").load('${pageContext.request.contextPath}/refreshinfo');
});
});
But the problem is, I have no idea how to get the value from my "#mutation" input field. I tried various ways to append it to my document and get it, but it either results in a new text field somewhere on the bottom of my page, or simply in a NULL value error. I have more ajax forms in the website which work fine, but they use elements that are hardcoded.
Every solution I could find was specifically for javascript-generated content, while my input doesn't get generated by javascript.
How would I go about extracting the value from my mutation input? Thanks a lot for any advice, the browser console isn't very helpful.
Get the value using js :
var mutation = document.getElementById('mutation').value;
or with jquery
var mutation = $('#mutation').val();
And pass mutation in your data or do what you need to with it

Load JavaScript model from fields on page

I learned some good things here here
What I want to know if it is possible to load these various JS model values, once the model is converted, from fields on the page without having to use
model.ProductId = $("#txtProductId").val();
What I mean, and this may be a dumb question, is there a way to type in data directly into the JS field? Like the #Html.TextBoxFor to load controller model field for JS variable?
My product form looks somewhat like this:
#model ProductModel
<form id="productForm">
<table>
<tr>
<td>#Html.TextBoxFor(o => o.BrandName, new {#id=txtBrandName})
///etc
One option you have is to use a javascript MVC framework like AngularJS, and then this will happen (more or less) automatically for you. You will probably want to create the text input using plain HTML instead of #Html.TextBoxFor.
For example, if you use AngularJS, your view would look like:
<input type="text" ng-model="model.ProductId" />
This creates a two-way data binding between your text box value and model.ProductId. What this means is that any time the user types a value into the text box, model.ProductId will automatically be set to the new value. Also any time you set model.ProductId in javascript, your text box will automatically update.
As a note, if you have any repeat sections in your view using #for loops, you will probably want to convert them to ng-repeat sections (for AngularJS at least).
I've found the best way to do this with a lot of help from Stephen Muecke. What I do is in the main page I have several DIVs:
<div id="divPerson" style="display: none"></div>
<div id="divProduct" style="display: none"></div>
In the JavaScript code I load each DIV with a partial view:
function loadPerson() {
$.ajax({
type: 'POST',
url: '#Url.Action("LoadPerson"),
success: function(data) {
$("#divPerson").html(data);
$("#divPerson").show();
}
});
And the controller method:
public ActionResult LoadPerson()
{
var model = new PersonModel();
return PartialView("PersonPage", model);
}
And in the PersonPage:
$(document).ready(function() {
$.validator.unobtrusice.parse();
});
And each field in this page has a class of 'personForm'.
This is to read the validation tags again after the page has loaded so that clicking next is this in the main page:
function goNext() {
if (!$("#form1").valid()) {
return false;
}
$.ajax({
type: 'POST',
url: '#Url.Action("AddPerson),
data: $(".personForm").serializeArray(),
success: function(data) {
$("#divProduct").html(data);
$("#divProduct").show();
$("#divPerson").hide();
}
});
I do the same thing for the product page by setting a certain class and serializing those controls to send to the controller.
This, to me, is a good balance between using MVC and jQuery to make the page smooth, crisp, and clean, and enhance the user experience.

Sending a list of values in Jquery to flask template

I am using:
Python 3.4
Flask 10.1
SQLAlchemy 0.9.6
JQuery 2.1.1
I'm working on a forum application that will show a table of forum threads based on tags selected by the user. The tags are a list of on/off buttons generated as per the below Jinja2 template. (Should be around 8, max 16 tags).
<UL class="ForumTagList">
{% for Tag in Forum.ForumTags.filter_by(Visible=True): %}
<li Class="ForumTag VisibleTrue" id ="liTag{{Tag.TagID}}" >
<input id="{{Tag.TagID}}" type="hidden" value="1" name="Name{{Tag.TagID}}"></input>
<DIV class="Tag{{Tag.TagID}}" onclick="toggle_tag('{{Tag.TagID}}');"> {{Tag.Name}}</DIV>
</li>
{% endfor %}
</UL>
There is a JS script that manages the changing of the values to 0 or 1.
The table will be loaded by an AJAX call as per below. It will initially load an unsorted table but the user will be able to refresh to see if new threads appear.
<script type="text/javascript">
$(document).ready(function(){
ThreadTableRefresh();
});
function ThreadTableRefresh(){
$('#ThreadsHolder').load('{{Forum.ForumID}}/ForumThreads');
}
</script>
<div id="ThreadsHolder">
</div>
I understand from reading the documentation on JQuerys Load Method that I can submit a second argument to the .load() method as an object. I hope to submit the on/off values from the users selection, which will then be used to generate the table only showing the tags the user wants.
I am very new to HTML and JQuery, would anyone be able to point me in the right direction as to how to take the various values from those HTML controls and post them as a list or dictionary to a Flask template?
If you need any addition information, please let me know.
You can send a dictionary or json to your flask template. For each TagID, there is a 1 or 0 value, e.g. {1:0, 2:0, 3:1, 4:0}.
Check out the .ajax jquery function to send a json object to your flask route. This should get you started.
Step by step:
click the refresh button
for each tag, add the id and toggle (1/0) value to a dictionary
convert the dictionary to a json object
use ajax function to send the object to your flask route
flask route takes the values, sends back the new html data
the ajax function will substitute the new html upon success
Javascript
$('#refresh-button').click(function() { //selector for refresh button
data = {}
$('input').each(function(){ //might need more specific selector
id = $(this).attr('id')
toggle = $(this).val()
data[id] = toggle
});
data = JSON.stringify(data);
$.ajax({
url: '/YourFlaskRoute'
type: 'POST',
data: data,
contentType: 'application/json;charset=UTF-8',
cache:false,
success: function (response) {
$(".ForumTagList").html(response); //your flask route needs to send back the html for just your list items
},
error: function(response){
alert('Error refreshing forum items')
}
});
});
Flask
#myblueprint.route('/YourFlaskRoute', methods = ['POST'])
def refresh_tags():
if request.method == 'POST':
data = request.json
#access your data
for key, value in data.items():
key = id
value = id
# run your query
tags = ...
#send back your list items template
return render_template('list_items.html', tags = tags)

jQuery Mobile and MVC3 auto submit

The following code works perfectly if I take jQuery Mobile out of the question!
The form:
#using (Html.BeginForm("SearchTown", "Home", FormMethod.Post, new { id = "TheForm1" }))
{
#Html.DropDownList("TownID", (SelectList)ViewBag.TownId, "Select a Town")
}
The Javascript:
<script type="text/javascript">
$(function () {
$("#TownID").live('change', function () {
//$("#TownID").change(function () {
var actionUrl = $('#TheForm1').attr('action') + '/' + $('#TownID').val();
$('#TheForm1').attr('action', actionUrl);
$('#TheForm1').submit();
});
});
</script>
But if I wrap jQuery Mobile around the site, then every time I submit the form, in my log only it tacks the ID field again and again to the end of the URL string. This only happens in my log, not in the browser. In the browser it still looks like it’s doing the right thing! E.g..
www.mysite.com/Home/SearchTown/2 the first time
www.mysite.com/Home/SearchTown/2/2 the second time
www.mysite.com/Home/SearchTown/2/2/2 the third time
But in the browser it still looks correct www.mysite.com/Home/SearchTown/2
Why is jQuery Mobile doing this?
This is most likely happening because each time you POST the form, it uses AJAX to load the response and the loaded page has repeated element IDs in it.
I'm guessing here, but based on what you described it sounds like your form posts back to a page with the same form markup on it. Each time your form post renders the next page you'll get another #TheForm1 added to your DOM (as jQuery Mobile keeps previously loaded pages in the DOM and simply swaps between active data-role="page" elements). Due to this behavior, once you have more than one #TheForm1 on the page, the selector $('#TheForm') will only ever return the first element in the DOM matching that ID- which will be the form which you posted the very first time. Thus, each time you you post, your code will use the action attribute of the form element you modified originally- which is why you see multiple values appended to the URL.
In jQuery Mobile it is almost always better to identify elements using a class name and the active page as the container, as you never know how many times an ID might be repeated in the DOM across multiple page changes. So, instead of using $('#TheForm1'), assign a class name and use that in conjunction with $.mobile.activePage: $('.Form1', $.mobile.activePage). (The same goes for your select box).
As an alternative, you can tell jQuery Mobile to not enhance your form by adding data-ajax="false" to the form tag. This will cause it to behave like a normal full page postback without any AJAX.
Edit
The point I am making in paragraph 3 is that you need to make sure you're always selecting the correct form element for the currently visible page, rather than unintentionally returning one which is hidden from view. The $.mobile.activePage global variable will give you the context of the currently visible page, and then a class-based selector (rather than Id-based) will ensure that the correct form element is retrieved in the change handler. Something like this:
<form class="town-form" action="#">
<select class="town-selector">
<option value="1">Town A</option>
<option value="2">Town B</option>
<option value="3">Town C</option>
</select>
</form>
<script type="text/javascript">
$(function () {
$(".town-selector").live('change', function () {
var form = $('.town-form', $.mobile.activePage);
var actionUrl = form.attr('action') + '/' + $(this).val();
form.attr('action', actionUrl);
alert('submitting to: ' + form.attr('action'));
form.submit();
});
});
</script>
because you are submitting the hole page and jQuery mobile does not fancy such thing, and after each POST it just appends the ID into the document.location... I have learned that in some mobile projects...
instead of this line $('#TheForm1').submit(); do something like this:
var url = $('#TheForm1').attr('action') + '/' + $('#TownID').val();
$.post(url, $('#TheForm1').serialize(), function(data) {
// do something with data if you send back something...
// or just change page with jQuery Mobile API
});
return false;
Iv'e left this one up long enough and no one has an answer!

Categories