Laravel ajax search in bootstrap modal - javascript

I want to use search bar inside bootstrap 4 modal header and display the search results in modal body with ajax get request.
Request is successful but,I can't get the results to show in the modal.
How do I display the results from request preview in a modal?
Controller:
public function index()
{
....
//MODAL IS A PARTIAL ON THE INDEX PAGE
return view('friends.index',compact('friends','friendRequests'));
}
public function search(Request $request)
{
if ($request->has('name')) {
$name = $request->query('name');
$results = User::where('name','like','%'.$name.'%')->get();
} else {
$results = User::all();
}
//RETURNING THE MODEL PARTIAL,BUT WITH RESULTS
return view('layouts.partials.friends.modal',compact('results'));
}
Relevant routes:
Route::get('/friends','FriendsController#index')->name('friends');
Route::get('/friends/search','FriendsController#search')
->name('searchFriend');
Index view:
<div class="container my-5">
<div class="row">
<h4><i class="fas fa-user-friends"> Friends:</i></h4>
</div>
<div class="row">
<button type="button" class="btn btn-outline-success mx-auto btn-lg"
data-toggle="modal" data-target=".add-friends-modal">
Add new <i class="fas fa-user-plus"></i>
</button>
</div>
//MODAL PARTIAL IS INCLUDED HERE
#include('layouts.partials.friends.modal')
<hr>
#include('layouts.partials.friends.friends-list')
Modal partial:
<div class="modal fade add-friends-modal" tabindex="-1" role="dialog"
aria-labelledby="friends-modal" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header ">
<div class="container">
<div class="row">
<div class="col-6 offset-3">
<h5 class="modal-title text-center">Add new friend:</h5>
</div>
<div class="row mx-auto">
<form class="form-inline mt-4 mb-4" action="javascript:search();">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"
id="search-input">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">
<i class="fas fa-search"></i>
</button>
</form>
</div>
</div>
</div>
<button type="button" class="close pull-right" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
//RESULTS SHOULD BE DISPLAYED HERE
#if(isset($results) && count($results)>0)
<ul>
#foreach($results as $result)
<li>{{ $result->name }}</li>
#endforeach
</ul>
#endif
</div>
</div>
searchAJAX.js
function search() {
var userInput = document.getElementById("search-input").value;
var xhttp = new XMLHttpRequest();
xhttp.open('GET','/friends/search?name='+userInput,true);
xhttp.send();
}

I suggest return just data instead of view. You can do something like that.
public function index()
{
....
//MODAL IS A PARTIAL ON THE INDEX PAGE
return view('friends.index',compact('friends','friendRequests'));
}
public function search(Request $request)
{
if ($request->has('name')) {
return User::where('name','like','%'.$name.'%')->get();
}
return response([]);
}
Modal Partial
<div class="modal fade add-friends-modal" tabindex="-1" role="dialog"
aria-labelledby="friends-modal" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header ">
<div class="container">
<div class="row">
<div class="col-6 offset-3">
<h5 class="modal-title text-center">Add new friend:</h5>
</div>
<div class="row mx-auto">
<form class="form-inline mt-4 mb-4" action="javascript:search();">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"
id="search-input">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">
<i class="fas fa-search"></i>
</button>
</form>
</div>
</div>
</div>
<button type="button" class="close pull-right" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="results"></div>
</div>
</div>
And JS File
function search() {
var resultsDiv = document.getElementById("results");
var req = new XMLHttpRequest();
req.responseType = "json";
req.open("GET", url, true);
req.onload = function() {
var users = req.response;
var content = "<ul>";
for (var user in users) {
content += "<li>" + user.name + "</li>";
}
content += "</ul>";
resultsDiv.innerHTML = content;
};
req.send(null);
}

Related

get specific id which is displayed from foreach loop to the script code

In my leave approval system admin can see the employee leave using foreach loop. Admin should approve or disapprove leave using the leave id.Im not clear on how to take the leave id from the view to my javascript file.
<script>
$(function(){
var BASE_URL = "http://localhost/employeemgt/index.php/";
$('#pedingLeaveRequest').on('show.bs.modal', function(event) {
var button = $(event.relatedTarget);
var current_leave_id = button.data('id');
var modal = $(this);
modal.find('input[name="current_leave_id"]').val(current_leave_id);
alert(current_leave_id);
});
$('#approvebtn').click(function(){
var id = $('input[name="current_leave_id"]').val();
alert(id);
$.post(BASE_URL + 'admin/AdminDashboardController/approveLeave',
{'id': id},
function(result){
console.log(result);
if(result.error){
// error
alert('try again');
}else{
// suceess
alert('Leave has been approved!');
}
});
});
});
</script>
This is the js file. The variable id is not working.
<?php
foreach ($leave as $row) {
echo '
<ul class="list-unstyled">
<li class="media border-bottom border-top py-3">
<img class="mr-3" src="http://via.placeholder.com/64x64" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">'.$row->user_name.'</h5>
<p class="mb-0 mt-0">'.$row->leave_start.' to '.$row->leave_end.'</p>
<p class="mt-0">'.$row->leave_type.'</p>
<p class="mt-0">'.$row->id.'</p>
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#pedingLeaveRequest">View Request</button>
</div>
</li>
</ul>
';
}
?>
above is the code where it display leave to the admin.
the following is the modal
<!-- Modal -->
<div class="modal fade" id="pedingLeaveRequest" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Leave Request</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12 mb-3">
<p class="mt-0 mb-1 font-weight-bold">Name</p>
<p class="mt-0 mb-0"><?php echo ''.$row->user_name.' '; ?></p>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="current_leave_id" value=""/>
<button type="button" id="declinebtn" class="btn btn-secondary" data-dismiss="modal">Decline</button>
<button type="button" id="approvebtn" class="btn btn-primary">Approve</button>
</div>
</div>
</div>
</div>
In your modal window, you have to add an input to store the current leave id. In your modal html add the following line.
<input type="hidden" name="current_leave_id" value=""/>
If you still don't have modal show event handler, add the following block. It saves the current leave id so when approve button is clicked, it will know which record to update.
$('#pedingLeaveRequest').on('show.bs.modal', function(event) {
var button = $(event.relatedTarget);
var current_leave_id = button.data('id');
var modal = $(this);
modal.find('input[name="current_leave_id"]').val(current_leave_id);
});
In your first code block - #approvebtn click handler..
Change:
var id = $(this).attr('data');
To:
var id = $('input[name="current_leave_id"]').val();
You can create the function on "onclick". In that function, you can add id which you get from foreach loop. but you have to create function leaveArrove(id) in javascript. add your javascript code in that function.
Try this
Ex:
Javascript code:
function leaveArrove(id){
$.post(BASE_URL + 'admin/AdminDashboardController/approveLeave',
{'id': id},
function(result){
console.log(result);
if(result.error){
// error
alert('try again');
}else{
// suceess
alert('Leave has been approved!');
}
});
}
Html Code:
<div id="showleave">
<h4 class="mb-4">Pending Requests</h4>
<?php
foreach ($leave as $row) {
echo '
<ul class="list-unstyled">
<li class="media border-bottom border-top py-3">
<img class="mr-3" src="http://via.placeholder.com/64x64" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">'.$row->user_name.'</h5>
<p class="mb-0 mt-0">'.$row->leave_start.' to '.$row->leave_end.'</p>
<p class="mt-0">'.$row->leave_type.'</p>
<p class="mt-0">'.$row->id.'</p>
<button type="button" name="addcart" onclick= "leaveArrove(<?php echo $row->id;?>)" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#pedingLeaveRequest" data-id="'.$row->id.'">View Request</button>
</div>
</li>
</ul>
';
}
?>
</div>

Knockout Uncaught RangeError: Maximum call stack size exceeded

I'm using Knockout Validation and when I post the view model to the controller I'm getting the exception "Uncaught RangeError: Maximum call stack size exceeded". I have one Main View Model because I'm using the CustomerViewModel in the same view (2 bootstrap modals), the first is to create a customer and the other one is to edit customer. Any idea of why is throwing the exception?
[HttpPost]
public JsonResult SaveCustomer(Customer model)
{
string status = "ok";
return Json(status, JsonRequestBehavior.AllowGet);
}
public class Customer
{
public string Name { get; set; }
}
$(document).ready(function () {
var CustomerSetupViewModel = function () {
var self = this;
self.Name = ko.observable("");
self.Validation = ko.validatedObservable([
self.Name.extend({
required: true
})
]);
var CustomerSetup = {
Name: self.Name
};
self.CustomerSetup = ko.observable();
self.GetCustomer = function () {
var data = { Name: "ToBeUpdated" };
self.CustomerSetup(data);
}
self.Save = function () {
if (self.Validation.isValid()) {
$.post("/Home/SaveCustomer", self, function (data) {
if (data == "ok")
alert("successful");
else
alert("error");
});
}
else {
self.Validation.errors.showAllMessages();
}
}
self.Update = function () {
var name = self.CustomerSetup().Name;
alert(name);
}
}
var MainViewModel = function () {
self = this;
self.NewCustomer = new CustomerSetupViewModel();
self.EditCustomer = new CustomerSetupViewModel();
}
vm = new MainViewModel();
ko.applyBindings(vm);
$("#updateCustomer").click(function () {
vm.EditCustomer.GetCustomer();
});
$("#NewCustomer").on("show.bs.modal", function (e) {
vm.NewCustomer.Name("");
vm.NewCustomer.Validation.errors.showAllMessages(false);
})
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<hr />
<a id="addCustomer" class="btn btn-default" data-toggle="modal" data-target="#NewCustomer">Add Customer</a>
<a id="updateCustomer" class="btn btn-default" data-toggle="modal" data-target="#UpdateCustomer">Update Customer</a>
<!-- Modal -->
<div id="NewCustomer" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="NewModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="NewModalLabel">New Customer</h4>
</div>
<div class="modal-body">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<label>Customer Name</label>
<input type="text" id="Name" class="form-control" data-bind="value: NewCustomer.Name" />
</div>
</div>
</div>
<div class="modal-footer">
<a role="button" class="btn btn-default" data-dismiss="modal">Close</a>
<a role="button" class="btn btn-primary" data-bind="click: NewCustomer.Save()">Save</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div id="UpdateCustomer" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="UpdateModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="UpdateModalLabel">Update Customer</h4>
</div>
<div class="modal-body">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body" data-bind="foreach: EditCustomer.CustomerSetup">
<div class="row">
<div class="col-md-4">
<label>Customer Name</label>
<input type="text" id="Name" class="form-control" data-bind="value: Name" />
</div>
</div>
</div>
<div class="modal-footer">
<a role="button" class="btn btn-default" data-dismiss="modal">Close</a>
<a role="button" class="btn btn-primary" data-bind="click: EditCustomer.Update">Update</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.js"></script>
I found the solution after using ko.toJSON() in the Save function. ko.toJSON() produces a JavaScript object with no Knockout constructs. And in that way I avoid the infinite loop.
self.Save = function () {
if (self.Validation.isValid()) {
$.post("/Home/SaveCustomer", ko.toJSON(self), function (data) {
if (data == "ok")
alert("successful");
else
alert("error");
});
}
else {
self.Validation.errors.showAllMessages();
}
}

Knockout loading and saving view model

I have the following code, is an example of one view model that I'm using in two sections (2 bootstrap modals). But I can't access the value from the second view model "UpdateviewModel". When I click Save button in the first Modal there is no problem, I get the Name value, but when I click Update button in the second modal the Name value is undefined. What am I doing wrong?
$(document).ready(function () {
CustomerSetupViewModel = function () {
var self = this;
self.Name = ko.observable();
var CustomerSetup = {
Name: self.Name
};
self.CustomerSetup = ko.observable();
self.GetCustomer = function () {
var data = { Name: "A00622" };
self.CustomerSetup(data);
}
Save = function () {
var test = viewModel.Name();
}
Update = function () {
var test2 = UpdateviewModel.Name();
}
}
var viewModel = new CustomerSetupViewModel();
var UpdateviewModel = new CustomerSetupViewModel();
ko.applyBindings(viewModel, document.getElementById("NewCustomer"));
ko.applyBindings(UpdateviewModel, document.getElementById("UpdateCustomer"));
$("#updateCustomer").click(function () {
UpdateviewModel.GetCustomer();
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<a id="addCustomer" class="btn btn-default" data-toggle="modal" data-target="#NewCustomer">Add Customer</a>
<a id="updateCustomer" class="btn btn-default" data-toggle="modal" data-target="#UpdateCustomer">Update Customer</a>
<!-- Modal -->
<div id="NewCustomer" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="NewModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="NewModalLabel">New Customer</h4>
</div>
<div class="modal-body">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<label>Customer Name</label>
<input type="text" id="Name" class="form-control" data-bind="value: Name" />
</div>
</div>
</div>
<div class="modal-footer">
<a role="button" class="btn btn-default" data-dismiss="modal">Close</a>
<a role="button" class="btn btn-primary" data-bind="click: Save">Save</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div id="UpdateCustomer" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="NewModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="NewModalLabel">New Customer</h4>
</div>
<div class="modal-body" data-bind="foreach: CustomerSetup">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<label>Customer Name</label>
<input type="text" id="Name" class="form-control" data-bind="value: Name" />
</div>
</div>
</div>
<div class="modal-footer">
<a role="button" class="btn btn-default" data-dismiss="modal">Close</a>
<a id="Update" class="btn btn-default" data-bind="click: Update">Update</a>
</div>
</div>
</div>
</div>
</div>
</div>
I am not sure about the problem, as I tried to log your UpdateviewModel it was an empty object.
I made your code works but there will be changes just for coding structure using mainViewModel and its subViewModel contents.
$(document).ready(function () {
var CustomerSetupViewModel = function () {
var self = this;
self.Name = ko.observable("");
self.Save = function () {
var test = self.Name();
alert(test);
}
self.Update = function () {
var test2 = self.Name();
alert(test2);
}
}
var MainViewModel = function () {
console.log("init")
self = this;
self.CustAdd = new CustomerSetupViewModel();
self.CustUpd = new CustomerSetupViewModel();
}
vm = new MainViewModel();
ko.applyBindings(vm);
$("#updateCustomer").click(function () {
vm.CustUpd.Name("ToBeUpdated");
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<a id="addCustomer" class="btn btn-default" data-toggle="modal" data-target="#NewCustomer">Add Customer</a>
<a id="updateCustomer" class="btn btn-default" data-toggle="modal" data-target="#UpdateCustomer">Update Customer</a>
<!-- Modal -->
<div id="NewCustomer" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="NewModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="NewModalLabel">New Customer</h4>
</div>
<div class="modal-body">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<label>Customer Name</label>
<input type="text" id="Name" class="form-control" data-bind="value: CustAdd.Name" />
</div>
</div>
</div>
<div class="modal-footer">
<a role="button" class="btn btn-default" data-dismiss="modal">Close</a>
<a role="button" class="btn btn-primary" data-bind="click: CustAdd.Save">Save</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div id="UpdateCustomer" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="UpdateModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="UpdateModalLabel">Update Customer</h4>
</div>
<div class="modal-body">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<label>Customer Name</label>
<input type="text" id="Name" class="form-control" data-bind="value: CustUpd.Name" />
</div>
</div>
</div>
<div class="modal-footer">
<a role="button" class="btn btn-default" data-dismiss="modal">Close</a>
<a role="button" class="btn btn-primary" data-bind="click: CustUpd.Update">Update</a>
</div>
</div>
</div>
</div>
</div>
</div>

Check the last and the first page and disable button next-previous buttons accordingly

I've 2 pop-ups to display the user list & admin list which would display 10 results per page, which is working fine.
I'm getting the page nos. from the java servlet in the JSON.
Note: There are 2 parameters passed in the url - resType and pageNo.
pageNo. returns 0, 10, 20 ...(multiples of 10).
resType: checks what sort of result I want. You can ignore this part.
So my url in the createTable function looks something like this instead -
How do I disable the previous button, when it is the first page? Likewise, how do I disable the last button, when it is the last page?
Here's the code.
var currentPageNo = 0; // Keep track of currently displayed page
$('.next-btn').unbind("click").on("click",function(){ // Give buttons an ID (include them in HTML as hidden)
userList(currentPageNo+10);
adminList(currentPageNo+10);
});
$('.prev-btn').unbind("click").on("click",function(){
userList(currentPageNo-10);
adminList(currentPageNo-10);
});
function userList(pageNo) {
var resType="userList";
createTable(resType,pageNo);
}
function adminList(pageNo) {
var resType="adminList";
createTable(resType,pageNo);
}
function createTable(resType, pageNo) {
// Update global variable
currentPageNo = pageNo;
// Set visibility of the "prev" button:
$('.prev-btn').toggle(pageNo > 0);
// Ask one record more than needed, to determine if there are more records after this page:
$.getJSON("https://api.randomuser.me/?results=11&start="+pageNo, function(data) {
$('#datatable tr:has(td)').empty();
// Check if there's an extra record which we do not display,
// but determines that there is a next page
$('.next-btn').toggle(data.results.length > 10);
// Slice results, so 11th record is not included:
data.results.slice(0, 10).forEach(function (record, i) { // add second argument for numbering records
var json = JSON.stringify(record);
$('#datatable').append(
$('<tr>').append(
$('<td>').append(
$('<input>').attr('type', 'checkbox')
.addClass('selectRow')
.val(json),
(i+1+pageNo) // display row number
),
$('<td>').append(
$('<a>').attr('href', record.picture.thumbnail)
.addClass('imgurl')
.attr('target', '_blank')
.text(record.name.first)
),
$('<td>').append(record.dob)
)
);
});
// Show the prev and/or buttons
}).fail(function(error) {
console.log("**********AJAX ERROR: " + error);
});
}
var savedData = []; // The objects as array, so to have an order.
function saveData(){
var errors = [];
// Add selected to map
$('input.selectRow:checked').each(function(count) {
// Get the JSON that is stored as value for the checkbox
var obj = JSON.parse($(this).val());
// See if this URL was already collected (that's easy with Set)
if (savedData.find(record => record.picture.thumbnail === obj.picture.thumbnail)) {
errors.push(obj.name.first);
} else {
// Append it
savedData.push(obj);
}
});
refreshDisplay();
if (errors.length) {
alert('The following were already selected:\n' + errors.join('\n'));
}
}
function refreshDisplay() {
$('.container').html('');
savedData.forEach(function (obj) {
// Reset container, and append collected data (use jQuery for appending)
$('.container').append(
$('<div>').addClass('parent').append(
$('<label>').addClass('dataLabel').text('Name: '),
obj.name.first + ' ' + obj.name.last,
$('<br>'), // line-break between name & pic
$('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
$('<label>').addClass('dataLabel').text('Date of birth: '),
obj.dob, $('<br>'),
$('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
obj.location.street, $('<br>'),
obj.location.city + ' ' + obj.location.postcode, $('<br>'),
obj.location.state, $('<br>'),
$('<button>').addClass('removeMe').text('Delete'),
$('<button>').addClass('top-btn').text('Swap with top'),
$('<button>').addClass('down-btn').text('Swap with down')
)
);
})
// Clear checkboxes:
$('.selectRow').prop('checked', false);
handleEvents();
}
function logSavedData(){
// Convert to JSON and log to console. You would instead post it
// to some URL, or save it to localStorage.
console.log(JSON.stringify(savedData, null, 2));
}
function getIndex(elem) {
return $(elem).parent('.parent').index();
}
$(document).on('click', '.removeMe', function() {
// Delete this from the saved Data
savedData.splice(getIndex(this), 1);
// And redisplay
refreshDisplay();
});
/* Swapping the displayed articles in the result list */
$(document).on('click', ".down-btn", function() {
var index = getIndex(this);
// Swap in memory
savedData.splice(index, 2, savedData[index+1], savedData[index]);
// And redisplay
refreshDisplay();
});
$(document).on('click', ".top-btn", function() {
var index = getIndex(this);
// Swap in memory
savedData.splice(index-1, 2, savedData[index], savedData[index-1]);
// And redisplay
refreshDisplay();
});
/* Disable top & down buttons for the first and the last article respectively in the result list */
function handleEvents() {
$(".top-btn, .down-btn").prop("disabled", false).show();
$(".parent:first").find(".top-btn").prop("disabled", true).hide();
$(".parent:last").find(".down-btn").prop("disabled", true).hide();
}
$(document).ready(function(){
$('#showExtForm-btn').click(function(){
$('#extUser').toggle();
});
$("#extUserForm").submit(function(e){
addExtUser();
return false;
});
});
function addExtUser() {
var extObj = {
name: {
title: "mr", // No ladies? :-)
first: $("#name").val(),
// Last name ?
},
dob: $("#dob").val(),
picture: {
thumbnail: $("#myImg").val()
},
location: { // maybe also ask for this info?
}
};
savedData.push(extObj);
refreshDisplay(); // Will show some undefined stuff (location...)
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#userList" onclick="userList(0)">User List</button>
<button class="btn btn-primary btn-sm" onclick="logSavedData()">Get Saved Data</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#adminList" onclick="adminList(0)">User Admin</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#extUser">Open External Form</button>
<div class="modal fade" id="userList" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">User List</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-hover" id="datatable">
<tr>
<th>Select</th>
<th>Name</th>
<th>DOB</th>
</tr>
</table>
</div>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
</div>
</div>
<br />
</div>
</div>
</div>
</div>
<div class="modal fade" id="adminList" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Admin List</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-hover" id="datatable">
<tr>
<th>Select</th>
<th>Name</th>
<th>DOB</th>
</tr>
</table>
</div>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
</div>
</div>
<br />
</div>
</div>
</div>
</div>
<div class="modal fade" id="extUser" role="dialog">
<div class="modal-dialog modal-lg">
<!-- External User-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Add External User</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" id="extUserForm">
<div class="form-group">
<label class="control-label col-sm-3" for="name">Name:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="name" name="name" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="myImg">Image:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="myImg" name="myImg" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="dob">DOB:</label>
<div class="col-sm-8">
<input type="date" class="form-control" id="dob" name="dob" required>
</div>
</div>
<hr />
<div class="form-group">
<div class="col-sm-offset-3 col-sm-3">
<button class="btn btn-primary btn-sm">Submit</button>
</div>
<div class="col-sm-3">
<button type="reset" class="btn btn-primary btn-sm">Reset</button>
</div>
<div class="col-sm-3">
<button type="button" class="btn btn-primary btn-sm close-external-modal" data-dismiss="modal">Close</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="container"></div>
In createTable a distinction should be made between which of the two tables you want to populate. So you should use a selector like:
$('#' + resType + ' table')
The same distinction should be made for the prev/next button selectors:
$('#' + resType + ' .next-btn')
And it is also wrong to call both userList and adminList in the same click handler, as it will make you skip a page of results (from 0 to 20). You should call the appropriate one based one the selector. So change your prev/next click handlers to:
// Select button that is descendant of userList
$('#userList .prev-btn').click(function(){
userList(currentPageNo-10);
});
$('#userList .next-btn').click(function(){
userList(currentPageNo+10);
});
$('#adminList .prev-btn').click(function(){
adminList(currentPageNo-10);
});
$('#adminList .next-btn').click(function(){
adminList(currentPageNo+10);
});
Finally, the code will hide the next button if you change one thing on the server: let it return 11 records instead of 10. The JavaScript code can then know if after the 10 records there is still more data (without showing the 11th record).
Here is updated code:
var currentPageNo = 0; // Keep track of currently displayed page
// Select button that is descendant of userList
$('#userList .prev-btn').click(function(){
userList(currentPageNo-10);
});
$('#userList .next-btn').click(function(){
userList(currentPageNo+10);
});
$('#adminList .prev-btn').click(function(){
adminList(currentPageNo-10);
});
$('#adminList .next-btn').click(function(){
adminList(currentPageNo+10);
});
function userList(pageNo) {
var resType="userList";
createTable(resType,pageNo);
}
function adminList(pageNo) {
var resType="adminList";
createTable(resType,pageNo);
}
function createTable(resType, pageNo) {
// Update global variable
currentPageNo = pageNo;
// Set visibility of the correct "prev" button:
$('#' + resType + ' .prev-btn').toggle(pageNo > 0);
// Ask one record more than needed, to determine if there are more records after this page:
$.getJSON("https://api.randomuser.me/?results=11&resType="+resType + "&pageIndex=" + pageNo, function(data) {
var $table = $('#' + resType + ' table');
$('tr:has(td)', $table).empty();
// Check if there's an extra record which we do not display,
// but determines that there is a next page
$('#' + resType + ' .next-btn').toggle(data.results.length > 10);
// Slice results, so 11th record is not included:
data.results.slice(0, 10).forEach(function (record, i) { // add second argument for numbering records
var json = JSON.stringify(record);
$table.append(
$('<tr>').append(
$('<td>').append(
$('<input>').attr('type', 'checkbox')
.addClass('selectRow')
.val(json),
(i+1+pageNo) // display row number
),
$('<td>').append(
$('<a>').attr('href', record.picture.thumbnail)
.addClass('imgurl')
.attr('target', '_blank')
.text(record.name.first)
),
$('<td>').append(record.dob)
)
);
});
// Show the prev and/or buttons
}).fail(function(error) {
console.log("**********AJAX ERROR: " + error);
});
}
var savedData = []; // The objects as array, so to have an order.
function saveData(){
var errors = [];
// Add selected to map
$('input.selectRow:checked').each(function(count) {
// Get the JSON that is stored as value for the checkbox
var obj = JSON.parse($(this).val());
// See if this URL was already collected (that's easy with Set)
if (savedData.find(record => record.picture.thumbnail === obj.picture.thumbnail)) {
errors.push(obj.name.first);
} else {
// Append it
savedData.push(obj);
}
});
refreshDisplay();
if (errors.length) {
alert('The following were already selected:\n' + errors.join('\n'));
}
}
function refreshDisplay() {
$('.container').html('');
savedData.forEach(function (obj) {
// Reset container, and append collected data (use jQuery for appending)
$('.container').append(
$('<div>').addClass('parent').append(
$('<label>').addClass('dataLabel').text('Name: '),
obj.name.first + ' ' + obj.name.last,
$('<br>'), // line-break between name & pic
$('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
$('<label>').addClass('dataLabel').text('Date of birth: '),
obj.dob, $('<br>'),
$('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
obj.location.street, $('<br>'),
obj.location.city + ' ' + obj.location.postcode, $('<br>'),
obj.location.state, $('<br>'),
$('<button>').addClass('removeMe').text('Delete'),
$('<button>').addClass('top-btn').text('Swap with top'),
$('<button>').addClass('down-btn').text('Swap with down')
)
);
})
// Clear checkboxes:
$('.selectRow').prop('checked', false);
handleEvents();
}
function logSavedData(){
// Convert to JSON and log to console. You would instead post it
// to some URL, or save it to localStorage.
console.log(JSON.stringify(savedData, null, 2));
}
function getIndex(elem) {
return $(elem).parent('.parent').index();
}
$(document).on('click', '.removeMe', function() {
// Delete this from the saved Data
savedData.splice(getIndex(this), 1);
// And redisplay
refreshDisplay();
});
/* Swapping the displayed articles in the result list */
$(document).on('click', ".down-btn", function() {
var index = getIndex(this);
// Swap in memory
savedData.splice(index, 2, savedData[index+1], savedData[index]);
// And redisplay
refreshDisplay();
});
$(document).on('click', ".top-btn", function() {
var index = getIndex(this);
// Swap in memory
savedData.splice(index-1, 2, savedData[index], savedData[index-1]);
// And redisplay
refreshDisplay();
});
/* Disable top & down buttons for the first and the last article respectively in the result list */
function handleEvents() {
$(".top-btn, .down-btn").prop("disabled", false).show();
$(".parent:first").find(".top-btn").prop("disabled", true).hide();
$(".parent:last").find(".down-btn").prop("disabled", true).hide();
}
$(document).ready(function(){
$('#showExtForm-btn').click(function(){
$('#extUser').toggle();
});
$("#extUserForm").submit(function(e){
addExtUser();
return false;
});
});
function addExtUser() {
var extObj = {
name: {
title: "mr", // No ladies? :-)
first: $("#name").val(),
// Last name ?
},
dob: $("#dob").val(),
picture: {
thumbnail: $("#myImg").val()
},
location: { // maybe also ask for this info?
}
};
savedData.push(extObj);
refreshDisplay(); // Will show some undefined stuff (location...)
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#userList" onclick="userList(0)">User List</button>
<button class="btn btn-primary btn-sm" onclick="logSavedData()">Get Saved Data</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#adminList" onclick="adminList(0)">User Admin</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#extUser">Open External Form</button>
<div class="modal fade" id="userList" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">User List</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-hover" id="datatable">
<tr>
<th>Select</th>
<th>Name</th>
<th>DOB</th>
</tr>
</table>
</div>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
</div>
</div>
<br />
</div>
</div>
</div>
</div>
<div class="modal fade" id="adminList" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Admin List</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-hover" id="datatable">
<tr>
<th>Select</th>
<th>Name</th>
<th>DOB</th>
</tr>
</table>
</div>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-offset-3 col-sm-4">
<button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
</div>
</div>
<br />
</div>
</div>
</div>
</div>
<div class="modal fade" id="extUser" role="dialog">
<div class="modal-dialog modal-lg">
<!-- External User-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Add External User</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" id="extUserForm">
<div class="form-group">
<label class="control-label col-sm-3" for="name">Name:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="name" name="name" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="myImg">Image:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="myImg" name="myImg" required>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="dob">DOB:</label>
<div class="col-sm-8">
<input type="date" class="form-control" id="dob" name="dob" required>
</div>
</div>
<hr />
<div class="form-group">
<div class="col-sm-offset-3 col-sm-3">
<button class="btn btn-primary btn-sm">Submit</button>
</div>
<div class="col-sm-3">
<button type="reset" class="btn btn-primary btn-sm">Reset</button>
</div>
<div class="col-sm-3">
<button type="button" class="btn btn-primary btn-sm close-external-modal" data-dismiss="modal">Close</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="container"></div>

jQuery plugin not working inside a .vue component

I'm working in a vue component for my application in Laravel 5.3, I try to integrate the Laravel File Manager in a standalone button, but this not working, nothing happend when I clic on the button for choose an image, this component required a jQuery init setup, like the following line:
$('.lfm-img').filemanager('image');
I checked the component outside the .vue file and its working fine, only inside the .vue file is not working.
This is the vue component
<template>
<div class="modal fade"
id="section-{{ section.id }}"
tabindex="-1"
role="dialog"
aria-labelledby="sectionLabel-{{ section.id }}">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button"
class="close"
data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="sectionLabel-{{ section.id }}">
{{ section.name }}
</h4>
</div>
<div class="modal-body">
<!-- Field List -->
<div v-if="editing != true">
<ul class="list-group">
<li class="list-group-item" v-for="field in fields">
<div class="clearfix">
<div class="pull-left">
<span>
{{ field.name }}
</span>
</div>
<div class="pull-right">
<button type="button"
class="btn btn-default"
data-toggle="tooltip"
title="Editar valor"
#click="setField(field)">
<i class="fa fa-pencil-square fa-lg"
aria-hidden="true"></i>
</button>
</div>
</div>
</li>
</ul>
</div>
<!-- / Field List -->
<!-- Save value form -->
<div v-else>
<form #submit.prevent="updateFieldValue()">
<!-- Fields types -->
<div v-if="field.fieldtype_id === 1">
<div class="form-group vertical-align">
<label class="col-md-2 text-right">
Texto
</label>
<div class="col-md-10">
<input type="text"
v-model="value"
placeholder="Ingrese el valor"
class="form-control"
required="required">
</div>
</div>
<p><br></p>
</div>
<div v-if="field.fieldtype_id === 2">
<div class="form-group">
<textarea v-model="value"
placeholder="Ingrese texto"
class="form-control"
rows="5"
required="required">
</textarea>
</div>
<p><br></p>
</div>
<div v-if="field.fieldtype_id === 3">
<div class="form-group vertical-align">
<label class="col-md-3 text-right">
Seleccione una imagen
</label>
<div class="col-md-9">
<div class="input-group">
<span class="input-group-btn">
<a data-input="value"
data-preview="holder"
class="btn btn-primary lfm-img">
<i class="fa fa-picture-o"
aria-hidden="true"></i> Seleccionar
</a>
</span>
<input id="value"
v-model="value"
class="form-control"
type="text"
name="value"
required="required">
</div>
</div>
</div>
<img id="holder" style="margin-top:15px;max-height:100px;">
<p><br></p>
</div>
<!-- Actions -->
<div class="clearfix">
<div class="pull-right">
<button type="button"
class="btn btn-default"
data-dismiss="modal"
#click="finishEdit()">
Cancelar
</button>
<button type="submit"
class="btn btn-primary">
Guardar
</button>
</div>
</div>
</form>
</div>
<!-- / Save value form -->
</div>
<div class="modal-footer">
<button type="button"
class="btn btn-default"
#click="finishEdit()"
data-dismiss="modal">
Cerrar
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['section'],
data()
{
return {
fields: [],
field: [],
value: '',
loading: true, // start the spin loader
editing: false // show field list
}
},
ready()
{
this.loading = false; // stop the spin loader
this.getSectionFields();
},
methods:
{
startEdit()
{
this.editing = true;
},
finishEdit()
{
this.field = [];
this.value = '';
this.editing = false;
},
setField(field) {
this.field = field;
if (this.field.pivot.value !== null) {
this.value = this.field.pivot.value;
}
this.startEdit();
},
getSectionFields()
{
var self = this; // store "this." scope
// GET request
this.$http.get('/api/getSectionFields/' + this.section.id )
.then((response) => {
// sucess callback
var json = JSON.parse(response.body); // json parse
self.fields = json.fields;
this.loading = false; // stop the spin loader
}, function(response) {
// error callback
console.log(response);
});
},
updateFieldValue()
{
this.loading = true // start the spin loader
var params = { section : this.section.id,
field : this.field.id,
value : this.value
};
// POST request
this.$http.post('/api/update-value', params)
.then((response) => {
// sucess callback
this.getSectionFields();
this.finishEdit();
}, function(response) {
// error callback
console.log(response);
this.getSectionFields();
});
}
}
}
</script>
I solved the problem using Vue.nextTick, running the following code before the file manager be shown to ensure the initialization of the plugins in the latest DOOM update.
initFilemanager()
{
this.$nextTick(function() {
$('.lfm-img').filemanager('image');
});
},

Categories