I'm making a live search function using ajax on laravel 7 and it works just fine for the most part. However, i have a button that disables the functions of the search output. When the page first loaded the functions are successfully disabled. But when i run the live search, the output's function is enabled again. I'm guessing its because the live search output is taken from a partial view/html which then loaded to the main view/html. The function run without any problem just after the page loads because the DOM already loaded it. When i append a new view/html, the DOM doesn't recognize it.
Here is the ajax code
function fetch_data(page, query){
$.ajax({
url:"/search?query="+query+"&page="+page,
success:function(data){
$('#product-container').html('');
$('#product-container').html(data);
}
});
}
$('#search').keyup(delay(function(){
var query = $('#search').val();
var page = $('#hidden_page').val();
fetch_data(page, query);
}, 400));
This is the partial view
<div class="row">
#if(count($products) < 1)
<div class="col-md-12 text-center">
<h5>No results</h5>
</div>
#endif
#foreach($products as $product)
<div class="col-md-3" id="item">
<div class="product__item p-2" style="background: #dce0e2;">
<div class="thumbnail">
<img src="{{ asset('img/products/'. $product->image) }}">
</div>
<div class="product__item__text">
<h6 style=" white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ $product->name }}</h6>
<h5>{{ rupiah($product->price) }}</h5>
</div>
<a href="{{ route('kasir.add.item', ['product_id' => $product->id]) }}" class="add-btn" id="{{ $product->id }}">
<div class="btn-success text-center m-2 p-1">
Add +
</div>
</a>
</div>
</div>
#endforeach
</div>
{{ $products->links('partials.pagination') }}
This is the controller
public function search(Request $request){
if ($request->ajax()) {
$query = $request->get('query');
$query = str_replace(" ", "%", $query);
$products = Product::orderBy('name', 'ASC')->where('name', 'LIKE', '%'.$query."%")->paginate(8);
return view('kasir.product_data', compact('products'))->render();
}
}
My question is can the DOM load the partial view as if it loaded at the same time as the page so that the jquery functions can work on the new view/html?
This should be your partial (only works if you add it through ajax requests). It will add the listeners you want, even after the DOM is completely loaded the first time. Rerunning the same piece of jQuery will re-establish the listeners you are expecting.
<div class="row">
....
</div>
{{ $products->links('partials.pagination') }}
<script>
$('#search').keyup(delay(function(){
var query = $('#search').val();
var page = $('#hidden_page').val();
fetch_data(page, query);
}, 400));
</script>
Related
this is image that i want to doactually i have a div content,i have apply onclick event on that div when user click on that div the text between these tags should be sent to server and then display in the table as well.i have done something guid me where is the error actually,because $.ajax not working it raising an error
e.g: $.ajax is not fnction
players.html
<div class="selectize-control single">
<div class="selectize-input items has-options not-full">
<input type="text" autocomplete="off" tabindex=""
id="select_player" style="width: 146.75px; opacity: 1; position:
relative; left: 0px;" placeholder="Adauga jucator la echipa">
</div>
<div class="selectize-dropdown single liststyle" id="listitems"
style="display: None; width: 987px; top: 29px; left: 0px; visibility:
visible;">
<div class="selectize-dropdown-content">
{% block listplayers %}
{% if player is not None %}
{% for p in player %}
<div class="option selected curserstyle sp" id="{{p.id}}" data-selectable="" data-value="{{p.YourName}}">{{p.YourName}}1</div>
<div class="option selected curserstyle sp" id="49" data-selectable="" data-value="{{p.YourName}}">{{p.YourName}}2</div>
{% endfor %}
{% else %}
<div class="text-center">
List is Empty
</div>
{% endif %}
{% endblock %}
</div>
</div>
</div>
javascript
$("#listitems").on('click',function(e){
// preventing from page reload and default actions
e.preventDefault();
// serialize the data for sending the form data.
var serializedData = $(this).serialize();
// make POST ajax call
$.ajax({
type:'get',
url:"/templates/dashboard/players",
data:serializedData,
success:function(responce){
// on successfull creating object
// 1. clear the form.
$("#listitems").trigger('reset');
// 2. focus to nickname input
$(".sp").focus();
// display the newly friend to table.
var instance = JSON.parse(response["instance"]);
var fields = instance[0]["fields"];
var x = document.getElementById(user_id).textContent;
$("#playername").append('<div class="row list-row player-row " id="targetdel'+i+'"><div class="col-md-6 title"><a id="playername" href="#">'+x+'</a></div><div class="col-md-2 company text-center has-checkbox"><label class="green checkbox-box"><input type="checkbox" class="checkbox_entity checkbox_captain" id="captain" data-entity_id="17270" data-entity_type="captain" data-url_ajax="update_team_player"><span class="checkmark"></span></label></div> <div class="col-md-2 company text-center has-checkbox"> <label class="green checkbox-box "><input type="checkbox" class=" checkbox_entity checkbox_observer " id="cd_btn" data-entity_id="'+i+'" data-entity_type="observer" data-url_ajax="update_team_player style="background-color:black;" "> <span class="checkmark"></span> </label></div><div class="col-md-2 actions company text-right"><a href="" class="remove_entity_data" data-entity_id="17270" data-entity_type="team_player" > </a><button id = "'+i+'" class="btn del" style="text-transform: none;background-color: #ed143d00;padding: 0px 9px;border: none;color: #a2a2a2;">x</button></div></div>');
i++;
},
error: function (response) {
// alert the error if any error occured
alert("this one is error");
alert(response["responseJSON"]["error"]);
},
})
})
Apart from you using response in the success of the ajax when you have function(responce), you may be using the slim build of Jquery.
You should make sure you are using the full version of Jquery as the slim build for some reason does not have ajax included in it.
An easy way to check is to go to where you have defined your scripts and see whether your script has slim in it.
This is, I believe, the latest full version of jquery. This is what you should have.
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
not this
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
I'm trying to insert modal window html code dynamically upon user click on which item otherwise i load all of the items' modal window code in the html. I also have some inputs in the modal window loading from Flask/Sql and i want to let user update any of them so i need to send data back to python on submit button clicked. But right now because of i have too many modal windows (even though they have separate ids) i couldn't find a way to achieve this
Here is my code:
routes.py
#app.route('/viewApart', methods=['GET', 'POST'])
def viewApart():
apts = []
getApts = db.engine.execute("SELECT * FROM apartments")
for a in getApts:
apts.append((a))
rooms = []
getRooms = db.engine.execute("SELECT * FROM rooms")
for r in getRooms:
rooms.append((r))
return render_template('apartments.html', title=_('Apartments'), apts=apts, rooms=rooms)
apartments.html
....
<section class="container">
<div class="row">
.. below some gallery code to show individual items from apts ..
{% for apt in apts %}
<div class="col-md-3">
<a href="javascript:void(0);" class="widget__v2 apt-widget rounded-corners box-shadow__v1 white" data-anchor="modalwindow" data-target="edit-apartment{{ apt[0] }}" id="apt{{ apt[0] }}">
<div class="widget-header">
<figure class="image h-180">
<img src="{{url_for('static', filename='_assets/img/apt/{{ apt[0] }}.jpg')}}" alt="" class="image__scaledown">
</figure>
.. below model window ..
<div id="edit-apartment{{ apt[0] }}" class="modal large">
<div class="modal-wrapper">
<div class="modal-inner">
<div class="modal-header">
<h3 class="title">{{ _('Edit Apartment') }}</h3>
</div>
<div class="modal-content">
<div class="row medium-gutter">
<div class="col-md-6">
<div class="row medium-gutter">
<div class="col-md-8">
<div class="form-group">
<div class="form-group-title clearfix">
<label for="apt_display_name">{{ _('Display Name') }}</label>
<div class="lh-24 text__default-grey pull-right" data-tooltip="true" data-tooltip-direction="up" data-multiline="true"
data-content="..">
<i class="icofont-question-circle"></i>
</div>
</div>
<input id="apt_display_name" type="text" class="form-control" value="{{ apt[1] }}">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="apt_number">{{ _('Apt. Number') }}</label>
<input id="apt_number" type="text" class="form-control" value="{{ apt[2] }}">
</div>
</div>
</div>
.. and so on...
.. and submit button ..
{{ _('Save Changes') }}
</div>
</section>
Right now even with multiple model windows, i can display the current data in modal window, so what i want to achieve this upon clicking on btnSubmit button i need to send all input values back to python so i can update my sql or insert new one. Please let me know if more code is needed..
Thanks
If I am understanding your question correctly - a skeleton version of your page would be something like this
<!DOCTYPE html>
<html>
<body>
<p>INTRODUCING MY AWESOME SITE AND 2 DIVS YOU CAN CLICK</p>
<div id="apt_1_modal">
<input id="apt_1_text"></input>
<a onclick="myFunction(event)">Submit</a>
</div>
<div id="apt_2_modal">
<input id="apt_2_text"></input>
<a onclick="myFunction(event)">Submit</a>
</div>
</body>
</html>
You will need JavaScript to handle the user interaction - the script would look something like this. You can either append this script directly to your render_template output or you can append it as a file.
The script will do 2 things - first capture what your user is inputting and second, send that data over to flask
<script>
function myFunction(e) {
//FIRST WE CAPTURE THE VALUE THAT THE USER INPUTS
let userInput = {toSend: e.currentTarget.previousElementSibling.value}
//THEN WE SEND IT TO THE FLASK BACKEND USING AJAX (Fetch API)
fetch("/api/path/to/flask/route", {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(userInput)
}
</script>
Now you need a function that can handle the userInput data
Backend
from flask import Flask, request #import main Flask class and request object
#app.route('/api/path/to/flask/route', methods=['POST'])
def capture_userinput():
req_data = request.get_json()
recd_data = req_data['toSend']
your_code_to_push_data_to_db(recd_data) #Depends on your ORM/DB
I hope I have given you an idea of how to go about - You will most certainly have to change the way to capture userInput, tweak the fetch call and send/capture additional data in your flask api.
Goal: Attempting to create a feature where a table is updated with added rows from the database.
I'm running into an issue with how the views are formatted, my knowledge with javascript and MVC isn't strong enough to know which direction to go.
I have the main view, and from there I load in three partialViews separately via an ajax call which populates the div with the defined ID
<div class="container-fluid">
<div id="preTestSteps">
</div>
<div id="mainTestSteps">
</div>
<div id="postTestSteps"></div>
</div>
With the following function that loads these partial views;
$(document).ready(function() {
var testSuiteExecutionId = #(Model.TestSuiteExecutionId);
var testSuiteId = #(Model.TestSuiteId);
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 1, "preTestSteps");
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 0, "mainTestSteps");
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 2, "postTestSteps");
});
function loadTestStepResultsPartialView( testSuiteExecutionId, testSuiteId, testStepType, divId) {
$.ajax({
type: 'POST',
url: '#Url.Action("DetailsTestStepResults", "TestSuiteExecutions")',
data: { 'testSuiteExecutionId': testSuiteExecutionId, 'testSuiteId': testSuiteId, 'testStepType': testStepType },
success: function(data) {
$("#" + divId).html(data);
}
});
}
This is working as intended.
Within these partial views, the model for the view is a list of view models, these view models are iterated over with the list of logs defined within them.
Partial View loaded from main view;
<div class="container-fluid">
#foreach (var testStep in Model)
{
<div class="row">
<div class="col-sm-12">
<h5 style="background-color: beige; padding: 5px">
#Html.DisplayFor(modelItem => testStep.TestStepName)
</h5>
</div>
</div>
<div>
#Html.Partial("~/Views/TestSuiteExecutions/TestStepLogsPartialView.cshtml", testStep.TestStepLogs)
</div>
<div>
#Html.Partial("~/Views/TestSuiteExecutions/TestStepLogsPartialView.cshtml", testStep.VerificationLogs)
<div style="padding-bottom: 25px" class="row"></div>
</div>
}
</div>
This is where things start breaking down. The partial views this partial view loads contain the logs and the table.
Log Partial View
#if (Model.Count > 0)
{
var accordianStepItemName = "accordianStep" + Model[0].TestStepId + Model[0].MessageType;
var collapseStepItemName = "collapseStep" + Model[0].TestStepId + Model[0].MessageType;
<!--TODO: Use PartialViews-->
<div class="row">
<div id="accordion" role="tablist" style="margin-left: 30px" aria-multiselectable="true">
<div id="transparent-card" class="card" style="border-color: white;">
<h6 class="mb-0">
<a data-toggle="collapse" data-parent="##accordianStepItemName" href="##collapseStepItemName" aria-expanded="false" aria-controls="#collapseStepItemName">
<i class="fa fa-plus"></i>
<i class="fa fa-minus"></i>
#(Model[0].MessageType == false ? Html.Raw("Verification Log") : Html.Raw("Execution Log"))
</a>
</h6>
<div id="#collapseStepItemName" class="collapse col-sm-12" role="tabpanel" aria-labelledby="headingOne">
<div class="card-body">
<table class="table" id="logTable_#Model[0].TestStepId#Model[0].MessageType">
<thead>
<tr>
<th width="5%"></th>
<th width="20% !important">Time</th>
<th width="75%">Message</th>
</tr>
</thead>
<tbody>
#foreach (var logEntry in Model)
{
<tr id="tableRow_#logEntry.TestStepId#logEntry.MessageType">
<td><img width="20" height="20" src="~/Content/Images/#HtmlUtilities.GetTestSuiteExecutionIconName(logEntry.LogType)" /></td>
<td><i>#logEntry.TimeStamp</i></td>
<td><i>#Html.Raw(HtmlUtilities.GetHtmlFormattedString(logEntry.Message))</i></td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
}
I'm attempting to write a javascrtipt method that will call an ajax call to bring up new log models in a list, and then add new rows to the table, but I'm running into two issues.
1) How do I pass the partial views table id's to the javascript function to execute the update? If I don't have the unique ID's (because this is looped and it needs unique Id's based on what I'm trying to update) then I can't even find the element to attach the new rows to in the script
2) How do I even attach to the table? I've attempted to use static data, but in attempting to access the table within the partial view to just prove I can actually add rows, I get 'getElementsByTagName' is null error in the debug menu.
Is what I'm attempting even possible with the current layout of the view(s)? Would it be better served to simply use one view model and put all of this logic on a single page to make the javascript easier to handle/actually function?
You can achieve this by following:
Create a partial view for row.
Segregate tables with some unique filters may be the css class.
Use those id to append rows.
I am building a twitter style feed with Laravel and jQuery.
My problem is that I'm sure I built this logic up badly.
So I have an included view what shows the tweet results.
Sending the data is just a basic ajax post with some DOM manipulation that's fine too.
After the form is submitted I display the fresh tweet with and append.
But the problem is no matter how i build my logic up, i always end up with duplication.
So what I do
Send the form, and the success function appends the data to the view
success: function(data) {
if(data.status === "success") {
$('#tweet-textarea').val("");
$('#tweets-wrapper').prepend(data.content);
}
},
And returning the goes the following way. After the tweet is saved, I return it in an array what I encode to json
$data = array('status' => 'success', 'content' =>
'<div class="tweet-box">
<div class="media">
<a class="pull-left" href="#">
<img src="http://placehold.it/60x60" alt="">
</a>
<div class="media-body">
<h4 class="media-heading">
'. $this->tweet->user->metadata->full_name .'
<small>'. "#".$this->tweet->user->username .'</small>
<small>'. $this->tweet->created_at .'</small>
</h4>
'. $this->tweet->message .'
</div>
</div>
</div>');
I know not the best way, and my problem is actually in my controller I am duplicating code, because the returned result "content in array" is the same just like in my view, so if I make any modification I need to make both
So is there a more effective way to do this?
You can use jQuery jPut Plugin to append json easily
<div jput="template">
<div class="tweet-box">
<div class="media">
<a class="pull-left" href="#">
<img src="http://placehold.it/60x60" alt="">
</a>
<div class="media-body">
<h4 class="media-heading">{{}}</h4>
</div>
</div>
</div>
</div>
<div id="main">
</div>
<script>
$(document).ready(function(){
//main is the div that you want to append
$('#main').jPut({
ajax_url:'domain.com/data.json', //your json data page
name:'template' //jPut template name
});
});
</script>
And in you json page no need to send all the div
$data = array('status' => 'success', 'content' => $this->tweet->user->metadata->full_name);
If you want to remove duplication of code, you are going to have to take all that logic out of your view and just pass it a nice long string for the entire section from your controller.
I'd start with making a function which can take a full name, username, timestamp, and message and create the tweet.
public function createTweet($fullName, $username, $created_at, $message)
{
return '<div class="tweet-box">
<div class="media">
<a class="pull-left" href="#">
<img src="http://placehold.it/60x60" alt="">
</a>
<div class="media-body">
<h4 class="media-heading">
'. $full_name .'
<small>'. "#".$username .'</small>
<small>'. $created_at .'</small>
</h4>
'. $message .'
</div>
</div>
</div>';
}
Then when you are looping through your tweets, call this function each time through and keep concatenating the response in a string, then you can just pass the string to your view and echo it there.
On your function which is returning ajax, do the same...
return Respons::json(array(
'status' => 'success',
'content' => $this->createTweet($this->tweet->user->metadata->full_name, $this->tweet->user->username, $this->tweet->created_at, $this->tweet->message)
));
You could also take a lot at HTML::macro() as well if you find yourself needing this functionality across your entire app. http://laravel-recipes.com/recipes/181 for a nice and quick HTML::macro() tut.
I have a comments section on my website and I need a way to make it update live (or every 30 seconds or so) It gets the comments from a mysql database with PHP:
<?php
$link = mysql_connect('localhost', 'root', '');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('SJCE');
$qu1 = mysql_query("SELECT `ID`,`contence`,`from`,`time`,`subject` FROM `***` WHERE `where` = 1 ORDER BY `time` DESC LIMIT 0 , 30");
$numr1 = mysql_num_rows($qu1);
$i = 1;
while($row=mysql_fetch_array($qu1)) {
$i++;
echo '
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading panel-title h3">
<div class="row">
<div class="col-xs-4">
<i class="fa fa-clock-o"></i> '.$row['3'].'
</div>
<div class="col-xs-4 text-center">
'.$row['4'].'
</div>
<div class="col-xs-4 text-right">
<i class="fa fa-user"></i> '.$row['2'].'
</div>
</div>
</div>
<div class="panel-body">
'.$row['1'].'
</div>
</div>
</div>
</div>
';
}
?>
and at the moment I use a piece of JavaScript to refresh the page:
<script type="text/javascript">
timeout = setTimeout("location.reload(true);",5000);
function disable_ar(){
clearTimeout(timeout);
}
function enable_ar(){
timeout = setTimeout("location.reload(true);",5000);
}
</script>
This works but makes the page flash every 5 seconds and sometimes causes it not to load properly.
I need a way to make the comments update without refreshing the whole page.
Thank you.
P.S. I know little about javascript, ajax and jquery
Load the jquery library:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
Then use an ajax script like this (must be called after jquery is loaded).
And use interval, not timeout (which only runs once).
$(function(){
window.setInterval(function(){
loadLatestResults();
}, 5000);
function loadLatestResults(){
$.ajax({
url : '/load/from/this/url.php',
cache : false,
success : function(data){
$('#id-of-element-into-which-results-are-loaded').html(data);
}
});
}
});