I have created a template for chat module. It was working fine yesterday but today there were some issues in some npm module so I ran the command npm audit fix --force and after that command is finished my chat template or any VUE template stops working means it is not showing up.
Here is the code of my template.
<template>
<div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span> Chat with {{ withUser.name }}
<button class="btn btn-warning btn-sm pull-right" #click="startVideoCallToUser(withUser.id)" type="button">
<span class="fa fa-video-camera"></span> Video Call
</button>
</div>
<div class="panel-body">
<ul class="chat" v-chat-scroll>
<li class="clearfix" v-for="message in messages" v-bind:class="{ 'right' : check(message.sender.id), 'left' : !check(message.sender.id) }">
<span class="chat-img" v-bind:class="{ 'pull-right' : check(message.sender.id) , 'pull-left' : !check(message.sender.id) }">
<img :src="'http://placehold.it/50/FA6F57/fff&text='+ message.sender.name" alt="User Avatar" class="img-circle" />
</span>
<div class="chat-body clearfix">
<div class="header">
<small class=" text-muted"><span class="glyphicon glyphicon-time"></span><timeago :since="message.created_at" :auto-update="10"></timeago></small>
<strong v-bind:class="{ 'pull-right' : check(message.sender.id) , 'pull-left' : !check(message.sender.id)}" class="primary-font">
{{ message.sender.name }}
</strong>
</div>
<p v-bind:class="{ 'pull-right' : check(message.sender.id) , 'pull-left' : !check(message.sender.id)}">
{{ message.text }}
</p>
<div class="row">
<div class="col-md-3" v-for="file in message.files">
<img :src="file.file_details.webPath" alt="" class="img-responsive">
<a :href="file.file_details.webPath" target="_blank" download>Download - {{ file.name }}</a>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="panel-footer">
<div class="input-group">
<input id="btn-input" type="text" v-model="text" class="form-control input-sm" placeholder="Type your message here..." />
<span class="input-group-btn">
<button class="btn btn-warning btn-sm" type="button" #click.prevent="send()" id="btn-chat">
Send
</button>
</span>
</div>
<div class="input-group">
<input type="file" multiple class="form-control">
<span class="input-group-btn">
<button class="btn btn-warning btn-sm" type="button" #click.prevent="sendFiles()">
Send Files
</button>
</span>
</div>
</div>
</div>
</div>
<div class="col-md-6 d-flex justify-center">
<video-section></video-section>
</div>
<div id="incomingVideoCallModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Incoming Call</h4>
</div>
<div class="modal-footer">
<button type="button" id="answerCallButton" class="btn btn-success">Answer</button>
<button type="button" id="denyCallButton" data-dismiss="modal" class="btn btn-danger">Deny</button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3" v-for="file in conversation.files">
<img :src="file.file_details.webPath" alt="" class="img-responsive">
<a :href="file.file_details.webPath" target="_blank" download>Download - {{ file.name }}</a>
</div>
</div>
</div>
</template>
<script>
$(function () {
var localVideo = document.getElementById('localVideo');
var remoteVideo = document.getElementById('remoteVideo');
var answerButton = document.getElementById('answerCallButton');
answerButton.onclick = answerCall;
$('input[type=file]').on('change', prepareUpload);
});
var files;
var conversationID;
var luid;
var ruid;
var startTime;
var localStream;
var pc;
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
var isCaller = false;
var peerConnectionDidCreate = false;
var candidateDidReceived = false;
export default {
props: ['conversation' , 'currentUser'],
data() {
return {
conversationId : this.conversation.conversationId,
channel : this.conversation.channel_name,
messages : this.conversation.messages,
withUser : this.conversation.user,
text : '',
constraints : {
audio: false,
video: true
},
}
},
methods: {
startVideoCallToUser (id) {
Cookies.set('remoteUUID', id);
window.remoteUUID = id;
luid = Cookies.get('uuid');
ruid = Cookies.get('remoteUUID');
isCaller = true;
start()
},
check(id) {
return id === this.currentUser.id;
},
send() {
var self = this;
axios.post('/chat/message/send',{
conversationId : this.conversationId,
text: this.text,
}).then((response) => {
this.listenForNewMessage();
self.text = '';
});
},
sendFiles() {
var data = new FormData();
$.each(files, function(key, value)
{
data.append('files[]', value);
});
data.append('conversationId' , this.conversationId);
axios.post('/chat/message/send/file', data);
},
listenForNewMessage: function () {
Echo.join(this.channel)
.here((users) => {
console.log(users)
})
.listen('\\PhpJunior\\LaravelVideoChat\\Events\\NewConversationMessage', (data) => {
var self = this;
if ( data.files.length > 0 ){
$.each( data.files , function( key, value ) {
self.conversation.files.push(value);
});
}
this.messages.push(data);
})
.listen('\\PhpJunior\\LaravelVideoChat\\Events\\VideoChatStart', (data) => {
if(data.to != this.currentUser.id){
return;
}
if(data.type === 'signal'){
onSignalMessage(data);
}else if(data.type === 'text'){
console.log('received text message from ' + data.from + ', content: ' + data.content);
}else{
console.log('received unknown message type ' + data.type + ' from ' + data.from);
}
});
},
},
beforeMount () {
Cookies.set('uuid', this.currentUser.id);
Cookies.set('conversationID', this.conversationId);
},
mounted() {
this.listenForNewMessage();
}
}
function onSignalMessage(m){
console.log(m.subtype);
if(m.subtype === 'offer'){
console.log('got remote offer from ' + m.from + ', content ' + m.content);
Cookies.set('remoteUUID', m.from);
onSignalOffer(m.content);
}else if(m.subtype === 'answer'){
onSignalAnswer(m.content);
}else if(m.subtype === 'candidate'){
onSignalCandidate(m.content);
}else if(m.subtype === 'close'){
onSignalClose();
}else{
console.log('unknown signal type ' + m.subtype);
}
}
function onSignalClose() {
trace('Ending call');
pc.close();
pc = null;
closeMedia();
clearView();
}
function closeMedia(){
localStream.getTracks().forEach(function(track){track.stop();});
}
function clearView(){
localVideo.srcObject = null;
remoteVideo.srcObject = null;
}
function onSignalCandidate(candidate){
onRemoteIceCandidate(candidate);
}
function onRemoteIceCandidate(candidate){
trace('onRemoteIceCandidate : ' + candidate);
if(peerConnectionDidCreate){
addRemoteCandidate(candidate);
}else{
//remoteCandidates.push(candidate);
var candidates = Cookies.getJSON('candidate');
if(candidateDidReceived){
candidates.push(candidate);
}else{
candidates = [candidate];
candidateDidReceived = true;
}
Cookies.set('candidate', candidates);
}
}
function onSignalAnswer(answer){
onRemoteAnswer(answer);
}
function onRemoteAnswer(answer){
trace('onRemoteAnswer : ' + answer);
pc.setRemoteDescription(answer).then(function(){onSetRemoteSuccess(pc)}, onSetSessionDescriptionError);
}
function onSignalOffer(offer){
Cookies.set('offer', offer);
$('#incomingVideoCallModal').modal('show');
}
function answerCall() {
isCaller = false;
luid = Cookies.get('uuid');
ruid = Cookies.get('remoteUUID');
$('#incomingVideoCallModal').modal('hide');
start()
}
function gotStream(stream) {
trace('Received local stream');
localVideo.srcObject = stream;
localStream = stream;
call()
}
function start() {
trace('Requesting local stream');
navigator.mediaDevices.getUserMedia({
audio: true,
video: {
width: {
exact: 320
},
height: {
exact: 240
}
}
})
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}
function call() {
conversationID = Cookies.get('conversationID');
trace('Starting call');
startTime = window.performance.now();
var videoTracks = localStream.getVideoTracks();
var audioTracks = localStream.getAudioTracks();
if (videoTracks.length > 0) {
trace('Using video device: ' + videoTracks[0].label);
}
if (audioTracks.length > 0) {
trace('Using audio device: ' + audioTracks[0].label);
}
var configuration = { "iceServers": [{ "urls": "stun:stun.ideasip.com" }] };
pc = new RTCPeerConnection(configuration);
trace('Created local peer connection object pc');
pc.onicecandidate = function(e) {
onIceCandidate(pc, e);
};
pc.oniceconnectionstatechange = function(e) {
onIceStateChange(pc, e);
};
pc.onaddstream = gotRemoteStream;
pc.addStream(localStream);
trace('Added local stream to pc');
peerConnectionDidCreate = true;
if(isCaller) {
trace(' createOffer start');
trace('pc createOffer start');
pc.createOffer(
offerOptions
).then(
onCreateOfferSuccess,
onCreateSessionDescriptionError
);
}else{
onAnswer()
}
}
function onAnswer(){
var remoteOffer = Cookies.getJSON('offer');
pc.setRemoteDescription(remoteOffer).then(function(){onSetRemoteSuccess(pc)}, onSetSessionDescriptionError);
pc.createAnswer().then(
onCreateAnswerSuccess,
onCreateSessionDescriptionError
);
}
function onCreateAnswerSuccess(desc) {
trace('Answer from pc:\n' + desc.sdp);
trace('pc setLocalDescription start');
pc.setLocalDescription(desc).then(
function() {
onSetLocalSuccess(pc);
},
onSetSessionDescriptionError
);
conversationID = Cookies.get('conversationID');
var message = {from: luid, to:ruid, type: 'signal', subtype: 'answer', content: desc, time:new Date()};
axios.post('/trigger/' + conversationID , message );
}
function onSetRemoteSuccess(pc) {
trace(pc + ' setRemoteDescription complete');
applyRemoteCandidates();
}
function applyRemoteCandidates(){
var candidates = Cookies.getJSON('candidate');
for(var candidate in candidates){
addRemoteCandidate(candidates[candidate]);
}
Cookies.remove('candidate');
}
function addRemoteCandidate(candidate){
pc.addIceCandidate(candidate).then(
function() {
onAddIceCandidateSuccess(pc);
},
function(err) {
onAddIceCandidateError(pc, err);
});
}
function onIceCandidate(pc, event) {
if (event.candidate){
trace(pc + ' ICE candidate: \n' + (event.candidate ? event.candidate.candidate : '(null)'));
conversationID = Cookies.get('conversationID');
var message = {from: luid, to:ruid, type: 'signal', subtype: 'candidate', content: event.candidate, time:new Date()};
axios.post('/trigger/' + conversationID , message );
}
}
function onAddIceCandidateSuccess(pc) {
trace(pc + ' addIceCandidate success');
}
function onAddIceCandidateError(pc, error) {
trace(pc + ' failed to add ICE Candidate: ' + error.toString());
}
function onIceStateChange(pc, event) {
if (pc) {
trace(pc + ' ICE state: ' + pc.iceConnectionState);
console.log('ICE state change event: ', event);
}
}
function onCreateSessionDescriptionError(error) {
trace('Failed to create session description: ' + error.toString());
}
function onCreateOfferSuccess(desc) {
trace('Offer from pc\n' + desc.sdp);
trace('pc setLocalDescription start');
pc.setLocalDescription(desc).then(
function() {
onSetLocalSuccess(pc);
},
onSetSessionDescriptionError
);
conversationID = Cookies.get('conversationID');
var message = {from: luid, to:ruid, type: 'signal', subtype: 'offer', content: desc, time:new Date()};
axios.post('/trigger/' + conversationID , message );
}
function onSetLocalSuccess(pc) {
trace( pc + ' setLocalDescription complete');
}
function onSetSessionDescriptionError(error) {
trace('Failed to set session description: ' + error.toString());
}
function gotRemoteStream(e) {
if (remoteVideo.srcObject !== e.stream) {
remoteVideo.srcObject = e.stream;
trace('pc received remote stream');
}
}
function trace(arg) {
var now = (window.performance.now() / 1000).toFixed(3);
console.log(now + ': ', arg);
}
function prepareUpload(event)
{
files = event.target.files;
}
</script>
<style>
.chat
{
list-style: none;
margin: 0;
padding: 0;
}
.chat li
{
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px dotted #B3A9A9;
}
.chat li.left .chat-body
{
margin-left: 60px;
}
.chat li.right .chat-body
{
margin-right: 60px;
}
.chat li .chat-body p
{
margin: 0;
color: #777777;
}
.panel .slidedown .glyphicon, .chat .glyphicon
{
margin-right: 5px;
}
.panel-body
{
overflow-y: scroll;
height: 250px;
}
::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #F5F5F5;
}
::-webkit-scrollbar
{
width: 12px;
background-color: #F5F5F5;
}
::-webkit-scrollbar-thumb
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #555;
}
And This is how I am calling my template in my blade template.
#section('content')
<div class="container-fluid">
<chat-room :conversation="{{ $conversation }}" :current-user="{{ auth()->user() }}"></chat-room>
</div>
#endsection
There are no errors in my laravel-echo-server nor in redis server nor in npm but still it is not showing up. I have tried some solutions but none of them are working.
Any help regarding this issue will be appreciated. Thank you in advance.
Can you check in Chrome dev tools for Javascript errors?
Related
I want to pass the data from the Laravel controller to the JS file then show it in the Laravel Blade view as it appears in the code
in this var dtUserTable = $('.user-list-table'),
user-list-table is a class that is called on the blade.php page. As it appears this is the call of it, how can I return the data from or pass the data from the Laravel controller to the JS file then show it in the blade.php file?
app-user-list.js
$(function () {
'use strict';
var dtUserTable = $('.user-list-table'),
newUserSidebar = $('.new-user-modal'),
newUserForm = $('.add-new-user'),
statusObj = {
1: { title: 'Pending', class: 'badge-light-warning' },
2: { title: 'Active', class: 'badge-light-success' },
3: { title: 'Inactive', class: 'badge-light-secondary' }
};
var assetPath = '../../../app-assets/',
userView = 'app-user-view.html',
userEdit = 'app-user-edit.html';
if ($('body').attr('data-framework') === 'laravel') {
assetPath = $('body').attr('data-asset-path');
userView = assetPath + 'app/user/view';
userEdit = assetPath + 'app/user/edit';
}
// Users List datatable
if (dtUserTable.length) {
dtUserTable.DataTable({
ajax: assetPath + 'data/user-list.json', // JSON file to add data
columns: [
// columns according to JSON
{ data: 'responsive_id' },
{ data: 'full_name' },
{ data: 'email' },
{ data: 'role' },
{ data: 'current_plan' },
{ data: 'status' },
{ data: '' }
],
columnDefs: [
{
// For Responsive
className: 'control',
orderable: false,
responsivePriority: 2,
targets: 0
},
{
// User full name and username
targets: 1,
responsivePriority: 4,
render: function (data, type, full, meta) {
var $name = full['full_name'],
$uname = full['username'],
$image = full['avatar'];
if ($image) {
// For Avatar image
var $output =
'<img src="' + assetPath + 'images/avatars/' + $image + '" alt="Avatar" height="32" width="32">';
} else {
// For Avatar badge
var stateNum = Math.floor(Math.random() * 6) + 1;
var states = ['success', 'danger', 'warning', 'info', 'dark', 'primary', 'secondary'];
var $state = states[stateNum],
$name = full['full_name'],
$initials = $name.match(/\b\w/g) || [];
$initials = (($initials.shift() || '') + ($initials.pop() || '')).toUpperCase();
$output = '<span class="avatar-content">' + $initials + '</span>';
}
var colorClass = $image === '' ? ' bg-light-' + $state + ' ' : '';
// Creates full output for row
var $row_output =
'<div class="d-flex justify-content-left align-items-center">' +
'<div class="avatar-wrapper">' +
'<div class="avatar ' +
colorClass +
' mr-1">' +
$output +
'</div>' +
'</div>' +
'<div class="d-flex flex-column">' +
'<a href="' +
userView +
'" class="user_name text-truncate"><span class="font-weight-bold">' +
$name +
'</span></a>' +
'<small class="emp_post text-muted">#' +
$uname +
'</small>' +
'</div>' +
'</div>';
return $row_output;
}
},
{
// User Role
targets: 3,
render: function (data, type, full, meta) {
var $role = full['role'];
var roleBadgeObj = {
Subscriber: feather.icons['user'].toSvg({ class: 'font-medium-3 text-primary mr-50' }),
Author: feather.icons['settings'].toSvg({ class: 'font-medium-3 text-warning mr-50' }),
Maintainer: feather.icons['database'].toSvg({ class: 'font-medium-3 text-success mr-50' }),
Editor: feather.icons['edit-2'].toSvg({ class: 'font-medium-3 text-info mr-50' }),
Admin: feather.icons['slack'].toSvg({ class: 'font-medium-3 text-danger mr-50' })
};
return "<span class='text-truncate align-middle'>" + roleBadgeObj[$role] + $role + '</span>';
}
},
{
// User Status
targets: 5,
render: function (data, type, full, meta) {
var $status = full['status'];
return (
'<span class="badge badge-pill ' +
statusObj[$status].class +
'" text-capitalized>' +
statusObj[$status].title +
'</span>'
);
}
},
{
// Actions
targets: -1,
title: 'Actions',
orderable: false,
render: function (data, type, full, meta) {
return (
'<div class="btn-group">' +
'<a class="btn btn-sm dropdown-toggle hide-arrow" data-toggle="dropdown">' +
feather.icons['more-vertical'].toSvg({ class: 'font-small-4' }) +
'</a>' +
'<div class="dropdown-menu dropdown-menu-right">' +
'<a href="' +
userView +
'" class="dropdown-item">' +
feather.icons['file-text'].toSvg({ class: 'font-small-4 mr-50' }) +
'Details</a>' +
'<a href="' +
userEdit +
'" class="dropdown-item">' +
feather.icons['archive'].toSvg({ class: 'font-small-4 mr-50' }) +
'Edit</a>' +
'<a href="javascript:;" class="dropdown-item delete-record">' +
feather.icons['trash-2'].toSvg({ class: 'font-small-4 mr-50' }) +
'Delete</a></div>' +
'</div>' +
'</div>'
);
}
}
],
order: [[2, 'desc']],
dom:
'<"d-flex justify-content-between align-items-center header-actions mx-1 row mt-75"' +
'<"col-lg-12 col-xl-6" l>' +
'<"col-lg-12 col-xl-6 pl-xl-75 pl-0"<"dt-action-buttons text-xl-right text-lg-left text-md-right text-left d-flex align-items-center justify-content-lg-end align-items-center flex-sm-nowrap flex-wrap mr-1"<"mr-1"f>B>>' +
'>t' +
'<"d-flex justify-content-between mx-2 row mb-1"' +
'<"col-sm-12 col-md-6"i>' +
'<"col-sm-12 col-md-6"p>' +
'>',
language: {
sLengthMenu: 'Show _MENU_',
search: 'Search',
searchPlaceholder: 'Search..'
},
// Buttons with Dropdown
buttons: [
{
text: 'Add New User',
className: 'add-new btn btn-primary mt-50',
attr: {
'data-toggle': 'modal',
'data-target': '#modals-slide-in'
},
init: function (api, node, config) {
$(node).removeClass('btn-secondary');
}
}
],
// For responsive popup
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal({
header: function (row) {
var data = row.data();
return 'Details of ' + data['full_name'];
}
}),
type: 'column',
renderer: $.fn.dataTable.Responsive.renderer.tableAll({
tableClass: 'table',
columnDefs: [
{
targets: 2,
visible: false
},
{
targets: 3,
visible: false
}
]
})
}
},
language: {
paginate: {
// remove previous & next text from pagination
previous: ' ',
next: ' '
}
},
initComplete: function () {
// Adding role filter once table initialized
this.api()
.columns(3)
.every(function () {
var column = this;
var select = $(
'<select id="UserRole" class="form-control text-capitalize mb-md-0 mb-2"><option value=""> Select Role </option></select>'
)
.appendTo('.user_role')
.on('change', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? '^' + val + '$' : '', true, false).draw();
});
column
.data()
.unique()
.sort()
.each(function (d, j) {
select.append('<option value="' + d + '" class="text-capitalize">' + d + '</option>');
});
});
// Adding plan filter once table initialized
this.api()
.columns(4)
.every(function () {
var column = this;
var select = $(
'<select id="UserPlan" class="form-control text-capitalize mb-md-0 mb-2"><option value=""> Select Plan </option></select>'
)
.appendTo('.user_plan')
.on('change', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? '^' + val + '$' : '', true, false).draw();
});
column
.data()
.unique()
.sort()
.each(function (d, j) {
select.append('<option value="' + d + '" class="text-capitalize">' + d + '</option>');
});
});
// Adding status filter once table initialized
this.api()
.columns(5)
.every(function () {
var column = this;
var select = $(
'<select id="FilterTransaction" class="form-control text-capitalize mb-md-0 mb-2xx"><option value=""> Select Status </option></select>'
)
.appendTo('.user_status')
.on('change', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? '^' + val + '$' : '', true, false).draw();
});
column
.data()
.unique()
.sort()
.each(function (d, j) {
select.append(
'<option value="' +
statusObj[d].title +
'" class="text-capitalize">' +
statusObj[d].title +
'</option>'
);
});
});
}
});
}
// Check Validity
function checkValidity(el) {
if (el.validate().checkForm()) {
submitBtn.attr('disabled', false);
} else {
submitBtn.attr('disabled', true);
}
}
// Form Validation
if (newUserForm.length) {
newUserForm.validate({
errorClass: 'error',
rules: {
'user-fullname': {
required: true
},
'user-name': {
required: true
},
'user-email': {
required: true
}
}
});
newUserForm.on('submit', function (e) {
var isValid = newUserForm.valid();
e.preventDefault();
if (isValid) {
newUserSidebar.modal('hide');
}
});
}
// To initialize tooltip with body container
$('body').tooltip({
selector: '[data-toggle="tooltip"]',
container: 'body'
});
});
Blade/View
#extends('panel.index')
#section('css-con')
<!-- BEGIN: Vendor CSS-->
<link rel="stylesheet" type="text/css" href="{{asset('app-assets/vendors/css/tables/datatable/dataTables.bootstrap4.min.css')}}">
<link rel="stylesheet" type="text/css" href="{{asset('app-assets/vendors/css/tables/datatable/responsive.bootstrap4.min.css')}}">
<link rel="stylesheet" type="text/css" href="{{asset('app-assets/vendors/css/tables/datatable/buttons.bootstrap4.min.css')}}">
<!-- END: Vendor CSS-->
<!-- BEGIN: Page CSS-->
<link rel="stylesheet" type="text/css" href="{{asset('app-assets/css/plugins/forms/form-validation.css')}}">
<link rel="stylesheet" type="text/css" href="{{asset('app-assets/css/pages/app-user.css')}}">
<!-- END: Page CSS-->
#endsection
#section('content')
<!-- users list start -->
<section class="app-user-list">
<!-- users filter start -->
<div class="card">
<h5 class="card-header">Search Filter</h5>
<div class="d-flex justify-content-between align-items-center mx-50 row pt-0 pb-2">
<div class="col-md-4 user_role"></div>
<div class="col-md-4 user_plan"></div>
<div class="col-md-4 user_status"></div>
</div>
</div>
<!-- users filter end -->
<!-- list section start -->
<div class="card">
<div class="card-datatable table-responsive pt-0">
<table class="user-list-table table">
<thead class="thead-light">
<tr>
<th></th>
<th>User</th>
<th>Email</th>
<th>Role</th>
<th>Plan</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
</table>
</div>
<!-- Modal to add new user starts-->
<div class="modal modal-slide-in new-user-modal fade" id="modals-slide-in">
<div class="modal-dialog">
<form class="add-new-user modal-content pt-0">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
<div class="modal-header mb-1">
<h5 class="modal-title" id="exampleModalLabel">New User</h5>
</div>
<div class="modal-body flex-grow-1">
<div class="form-group">
<label class="form-label" for="basic-icon-default-fullname">Full Name</label>
<input type="text" class="form-control dt-full-name" id="basic-icon-default-fullname" placeholder="John Doe" name="user-fullname" aria-label="John Doe" aria-describedby="basic-icon-default-fullname2" />
</div>
<div class="form-group">
<label class="form-label" for="basic-icon-default-uname">Username</label>
<input type="text" id="basic-icon-default-uname" class="form-control dt-uname" placeholder="Web Developer" aria-label="jdoe1" aria-describedby="basic-icon-default-uname2" name="user-name" />
</div>
<div class="form-group">
<label class="form-label" for="basic-icon-default-email">Email</label>
<input type="text" id="basic-icon-default-email" class="form-control dt-email" placeholder="john.doe#example.com" aria-label="john.doe#example.com" aria-describedby="basic-icon-default-email2" name="user-email" />
<small class="form-text text-muted"> You can use letters, numbers & periods </small>
</div>
<div class="form-group">
<label class="form-label" for="user-role">User Role</label>
<select id="user-role" class="form-control">
<option value="subscriber">Subscriber</option>
<option value="editor">Editor</option>
<option value="maintainer">Maintainer</option>
<option value="author">Author</option>
<option value="admin">Admin</option>
</select>
</div>
<button type="submit" class="btn btn-primary mr-1 data-submit">Submit</button>
<button type="reset" class="btn btn-outline-secondary" data-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Modal to add new user Ends-->
</div>
<!-- list section end -->
</section>
<!-- users list ends -->
#endsection
#section('jc-con')
<!-- BEGIN: Page Vendor JS-->
<script src="{{asset('app-assets/vendors/js/tables/datatable/jquery.dataTables.min.js')}}"></script>
<script src="{{asset('app-assets/vendors/js/tables/datatable/datatables.bootstrap4.min.js')}}"></script>
<script src="{{asset('app-assets/vendors/js/tables/datatable/dataTables.responsive.min.js')}}"></script>
<script src="{{asset('app-assets/vendors/js/tables/datatable/responsive.bootstrap4.js')}}"></script>
<script src="{{asset('app-assets/vendors/js/tables/datatable/datatables.buttons.min.js')}}"></script>
<script src="{{asset('app-assets/vendors/js/tables/datatable/buttons.bootstrap4.min.js')}}"></script>
<script src="{{asset('app-assets/vendors/js/forms/validation/jquery.validate.min.js')}}"></script>
<!-- END: Page Vendor JS-->
<!-- BEGIN: Page JS-->
<script src="{{asset('app-assets/js/scripts/pages/app-user-list.js')}}"></script>
<!-- END: Page JS-->
#endsection
Below is the function that I call when I want to get the data in the Laravel controller.
public function list()
{
$data = DB::table('users')->get();
return view('content.apps.user.user-list',compact('data'));
}
blade
#push('scripts')
<script>
//line chart
var line = new Morris.Line({
element: 'line-chart',
resize: true,
data: [
#foreach ($data as $value)
{
ym: "{{ $value->year }}-{{ $value->month }}", sum: "{{ $value->sum }}"
},
#endforeach
],
xkey: 'ym',
ykeys: ['sum'],
labels: ['#lang('site.total')'],
lineWidth: 2,
gridTextFamily: 'Open Sans',
gridTextSize: 10
});
</script>
#endpush
I write some python code and want to use xpath to read a value from webpage "http://www.aastocks.com/en/stocks/quote/detail-quote.aspx?symbol=00371", but it shows "IndexError: list index out of range". After I check the page.content, I cannot find the value of field "P/B Ratio" in the content. Does anyone know how to get the "P/B Ratio" value? Thanks!
My code as below:
```
#TestXPath.py
from lxml import html
import requests
import threading
URL = 'http://www.aastocks.com/en/stocks/quote/detail-quote.aspx?symbol=00371'
XPATH = '//*[#id="tbPBRatio"]/div[2]'
def getValue():
page = requests.get(URL)
print (page.content)
tree = html.fromstring(page.content)
value = tree.xpath(XPATH)
print('value={0!s}'.format(value[0]))
if __name__ == "__main__":
getValue()
```
Captured an image for reference
The part of the output of page.content is here:
<script type="text/javascript">_gaq.push(['a2._setAccount', 'UA-129684769-1']); _gaq.push(['a2._trackPageview']);</script><meta property="fb:app_id" content="280135662816939" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="keywords" content="HK Stocks, Quote, Detailed Quote, Fund, Warrants, CBBCs, Call, Put, News, Technical Chart, Blocked Trade, HK Indices, CN Indices" /><meta name="description" content="HK Stock Detail Quote provides information including Free HK-share Real-time Quote, HK-share Chart, HK-share Historical Performance, HK-share Technical Chart, Related A-share Quote, HK-share PE Ratio, HK-share Yield, HK-share Earnings Per Share, HK-share Dividend Payout, HK-share PB Ratio, HK-share Moneyflow, HK-share NAV, A + H + ADR, HK-share News, HK-share related warrants, HK-share related CBBC" /><link href="/en/favicon.ico?v=1.2.0" rel="icon" /><link href="/en/favicon.ico?v=1.2.0" rel="shortcut icon" type="image/x-icon" /><title>
Detail Quote
</title></head> <body id="stock" class="eng resizeable"> <div id="divFSMask" style="position:absolute; filter:alpha(opacity=80); zoom:1; opacity:0.8; top:0px; left:0px; width:100%; background:black; height:100%; z-index:100; display:none"></div> <div id="CrazyiPadPopup"><script type='text/javascript'>OA_show('Crazy_iPad_popup');</script></div> <div class="div980"></div> <script type="text/javascript">
is980Mode = $(".div980").is(":visible");
curWidth980Mode = is980Mode;
$(window).resize(function () {
is980Mode = $(".div980").is(":visible");
});
</script> <form method="post" action="detail-quote.aspx?symbol=00371" id="mainForm"> <div class="aspNetHidden"> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="Z9MEfrcXHWZHLrGNyFqv+7SMlO6SiAMa7mXGDMSld4HEXzCSEoFrPdihSEdNmeLlfp2baKFj4zokP6U4qIkQHqDHMWXV/jmGUoqV4SMh5eVDRMAt9R/uTpjoNRENJ1gJvpq1WfDuqhOk4bgLGuMIkVrrNVEeulw+uPlpfk6+IKGUlf+oGGm8+uEqAJVbXuwF7hwKJVAhb+gPc1EHEzmjBIzKhwYZjVkVemPXQREWHgctAZfQ3kZ+m/+hQp5V6+DW/SNkXGj9RrdVnH8CGZW3RXbgouS/d8cUOOFkzBEApi5R5S+TDmf5xuXNPFuJk256LtjbwXKQUVvM14wt+6GuXYyBpKnaRmwypcbUrmbtCd0dN0Y0" /> </div> <div class="container"> </div> <div class="container" style="position:relative; z-index:3;" id="divMasterHead"> <div id="topPanel"> <div class="blue-line"> <div class="container"> <div class="float_l AASTOCKSHome" style="position:relative; top:10px; "> <div style="height: 20px; line-height: 20px; padding-left:0px;" class="float_l icon_marginright" onclick="setHomepage()"><div class="header_icon_map icon_sethome jshoverwithclass" hover="hoveron"></div></div> <div style="height: 20px; line-height: 20px; padding-left:0px;" class="float_l icon_marginright"><div class="header_icon_map icon_contact jshoverwithclass" hover="hoveron"></div></div> <div style="width:1px; height: 20px; line-height: 20px; background-color:#006e97;" class="float_l icon_marginright"></div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright lang-btn"><a id="bLang1" class="jshoverwithclass tc" hover="hoveron" href="javascript:toLang('tc')">繁</a></div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright lang-btn"><a id="bLang2" class="jshoverwithclass sc" hover="hoveron" href="javascript:toLang('sc')">简</a></div> <div style="width:1px; height: 20px; line-height: 20px; background-color:#006e97;" class="float_l icon_marginright"></div> <div style="height: 20px; line-height: 20px; padding-left:0px;" class="float_l icon_marginright"><div class="header_icon_map icon_facebook jshoverwithclass" hover="hoveron"></div></div> <div style="width:1px; height: 20px; line-height: 20px; background-color:#006e97;" class="float_l icon_marginright"></div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright"> <div class="topslidebox"> <div style="position:absolute; width:100%; height:100%; z-index:1;"></div> <table><tr><td><div class="header_icon_map icon_topiphone"></div></td><td style="padding-left:9px;"><span style="white-space:nowrap;">Market+ (iPhone)</span></td></tr></table> </div> </div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright"> <div class="topslidebox"> <div style="position:absolute; width:100%; height:100%; z-index:1;"></div> <table><tr><td><div class="header_icon_map icon_topandroid"></div></td><td style="padding-left:9px;"><span style="white-space:nowrap;">Market+ (Android)</span></td></tr></table> </div> </div> <div style="height: 20px; line-height: 20px;" class="float_l"> <div class="topslidebox"> <div style="position:absolute; width:100%; height:100%; z-index:1;"></div> <table><tr><td><div class="header_icon_map icon_topmobile"></div></td><td style="padding-left:13px;"><span style="white-space:nowrap;">Mobile Site</span></td></tr></table> </div> </div> </div> <div class="tp-box float_r usq " onclick="window.location.href='/en/usq/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">US STOCKS</div> </div> <div class="tp-box float_r " onclick="window.location.href='/en/funds/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">FUNDS</div> </div> <div class="tp-box float_r " onclick="window.location.href='/en/forex/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">FOREX</div> </div> <div class="tp-box float_r " onclick="window.location.href='/en/cnhk/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">SH/SZ-HK</div> </div> <div class="tp-box float_r sel" onclick="window.location.href='/en/'"> <div class="bold " hover="hoveron">HK STOCKS</div> </div> <div class="tp-box float_r aabest" onclick="gotoAABEST('https://www.aabest.com/en/default.aspx');"> <div class="float_l header_icon_map icon_aabest"></div> </div> <div class="clear"></div> </div> </div> <script type="text/javascript">
/* Forex Function */
function forexquote() {
quote($("#txtCurSymbol").val());
}
function forexchartquote() {
fxchart($("#txtCurSymbol").val());
}
function fxchart(value) {
window.location.href = "/en/forex/quote/chart.aspx?symbol=" + value;
}
function quote(value) {
if (value == "UDI") {
window.location.href = "/en/forex/quote/dollarindex.aspx";
} else {
window.location.href = "/en/forex/quote/quote.aspx?symbol=" + value;
}
}
/* End of Forex Function */
/* US Function */
function uschart(value) {
window.location.href = "/en/usq/quote/chart.aspx?symbol=" + encodeURIComponent(value);
}
function usquotewvalue() {
usquote($("#txtUSQuote").val());
}
function usquotewvalue2() {
usquote($("#txtCurSymbol").val());
}
function uschartwvalue() {
uschart($("#txtUSQuote").val());
}
function uschartwvalue2() {
uschart($("#txtCurSymbol").val());
}
function usquote(value) {
window.location.href = "/en/usq/quote/quote.aspx?symbol=" + encodeURIComponent(value);
}
// End of US Function
// Stock Function
function hkquotewvalue() {
var symbol = $("#txtHKQuote").val();
symbol = ('Code/Name' == symbol ? '00001' : symbol);
hkquote(symbol);
}
function hkchartwvalue() {
var symbol = $("#txtHKQuote").val();
symbol = ('Code/Name' == symbol ? '00001' : symbol);
hkchart(symbol);
}
function hkquote(value) {
window.location.href = "/en/stocks/quote/quick-quote.aspx?symbol=" + encodeURIComponent(value);
}
function hkchart(value) {
window.location.href = '/en/stocks/quote/detailchart.aspx?symbol=' + encodeURIComponent(value);
}
function hknewswvalue(value) {
var symbol = value;
symbol = ('Code/Name' == symbol ? '00001' : symbol);
window.location.href = '/en/stocks/analysis/stock-aafn/{0}/{1}/{2}/{3}'.replace("{0}", symbol).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function hknews() {
var symbol = $("#txtHKQuote").val();
symbol = ('Code/Name' == symbol ? '00001' : symbol);
window.location.href = '/en/stocks/analysis/stock-aafn/{0}/{1}/{2}/{3}'.replace("{0}", symbol).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function hknews2(value) {
window.location.href = '/en/stocks/analysis/stock-aafn/{0}/{1}/{2}/{3}'.replace("{0}", value).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
/* End of Stock Function */
/* CN Quote Function */
function cnquote(value) {
if (GetDefaultQuoteSetting() == "QQ")
window.location.href = "/en/cnhk/quote/quick-quote.aspx?shsymbol=" + encodeURIComponent(value);
else
window.location.href = "/en/cnhk/quote/detail-quote.aspx?shsymbol=" + encodeURIComponent(value);
}
function cnchart(value) {
window.location.href = "/en/cnhk/analysis/tech-chart.aspx?shsymbol=" + encodeURIComponent(value);
}
function cnnews(value) {
window.location.href = '/en/cnhk/quote/stock-news/{0}/{1}/{2}/{3}/'.replace("{0}", encodeURIComponent(value)).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function cnquotewvalue() {
var symbol = $("#txtCNQuote").val();
symbol = ("Code/Name" == symbol ? '600000' : symbol);
cnquote(symbol);
}
function cnchartwvalue() {
var symbol = $("#txtCNQuote").val();
symbol = ('Code/Name' == symbol ? '600000' : symbol);
cnchart(symbol);
}
function cnnewswvalue() {
var symbol = $("#txtCNQuote").val();
symbol = ('Code/Name' == symbol ? '600000' : symbol);
window.location.href = '/en/cnhk/quote/stock-news/{0}/{1}/{2}/{3}/'.replace("{0}", symbol).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function shhkquote(s, type, passInMarket) {
type = type == undefined ? 'quote' : type;
var market = 'SH';
if (passInMarket == 'US') {
market = 'US';
s = ('Code/Name' == s ? 'AAPL' : s);
} else {
if (s.length == 6) {
market = 'SH';
} else {
s = ('Code/Name' == s ? '00001' : s);
s = '00000' + s;
s = s.substr(s.length - 5, 5)
market = 'HK';
}
}
switch (type) {
case 'quote':
$("#mainForm").submit(function (e) { return false; });
if (market == 'SH')
cnquote(s);
else if (market == 'US')
usquote(s);
else {
SetLTP(fullCookiesDomain);
hkquote(s);
}
break;
case 'chart':
$("#mainForm").submit(function (e) { return false; });
if (market == 'SH')
cnchart(s);
else if (market == 'US')
uschart(s);
else
hkchart(s);
break;
case 'news':
$("#mainForm").submit(function (e) { return false; });
if (market == 'SH')
cnnews(s);
else
hknewswvalue(s);
break;
}
return false;
}
/* End of CN Quote Function */
/* DZH Function */
function dzhquotewvalue() {
dzhquote($("#txtCurSymbol").val());
}
function dzhquote(value) {
window.location.href = "/en/dzh/quote/quote.aspx?symbol=" + value;
}
function dzhchart(value) {
window.location.href = "/en/dzh/quote/chart.aspx?symbol=" + value;
}
function dzhnews(value) {
window.location.href = "/en/dzh/quote/news.aspx?symbol=" + value;
}
/* End of DZH Function */
function toLang(v) {
var pathname = window.location.pathname;
var search = window.location.search;
var hash = window.location.hash;
if (pathname != undefined && pathname != null) {
pathname = pathname.toLowerCase();
}
if (pathname.indexOf("/tc/") >= 0) {
$.cookie("mLang", "TC", { expires: GetExpiryDate(), path: '/', domain: subCookiesDomain });
window.location.href = pathname.replace("/tc/", "/" + v + "/") + search + hash;
} else if (pathname.indexOf("/sc/") >= 0) {
$.cookie("mLang", "SC", { expires: GetExpiryDate(), path: '/', domain: subCookiesDomain });
window.location.href = pathname.replace("/sc/", "/" + v + "/") + search + hash;
} else if (pathname.indexOf("/en/") >= 0) {
$.cookie("mLang", "EN", { expires: GetExpiryDate(), path: '/', domain: subCookiesDomain });
window.location.href = pathname.replace("/en/", "/" + v + "/") + search + hash;
} else {
window.location.href = "/" + v + pathname + search + hash;
}
}
</script>
when I reload browser I can see the post's pics
I have a component referring to the posts, but when you make a post that contains images, they are not updated and the post remains with the images from the previous post, the only way to prevent this from happening is by updating the browser and it should not be like that
Could someone help me to know what is happening, if I should update the component when loading the images or what should I do?
Thanks!
fomPost.vue =>
<template>
<div class="card bg-dark border-left-primary border-right-primary shd mb-4">
<div class="card-body">
<div v-if="status_msg" :class="{ 'alert-green': status, 'alert-danger': !status }" class="alert"
role="alert">{{ status_msg }}
</div>
<div class="form-group">
<textarea id="content-body" class="form-control" v-model="body"></textarea>
<a href="javascript:void(0)" class="text-lg float-right" data-toggle="tooltip"
data-title="Agregar imágenes" data-placement="bottom" #click="toggle()">
<i class="fas fa-cloud-upload-alt"></i>
</a>
</div>
<div v-show="isOpen" :style="'margin-top: 2rem'">
<div class="uploader"
#dragenter="OnDragEnter"
#dragleave="OnDragLeave"
#dragover.prevent
#drop="onDrop"
:class="{ dragging: isDragging }">
<div class="upload-control" v-show="images.length">
<label for="file">Agregar más imágenes</label>
</div>
<div v-show="!images.length">
<p>Arrastra las imágenes ó</p>
<div class="file-input">
<label for="file">Selecciónalas</label>
<input type="file" id="file" #change="onInputChange"
accept="image/x-png,image/gif,image/jpeg" multiple>
</div>
</div>
</div>
<div class="images-preview" v-show="images.length">
<div class="img-wrapper" v-for="(image, index) in images" :key="index">
<div class="thumbnail" :style="`background-image: url(${image.replace(/(\r\n|\n|\r)/gm)})`">
<div class="options">
<div>
<a href="javascript:void(0)" class="text-light" uk-tooltip="title: Eliminar"
#click="removeimage(index)">
<i class="fas fa-trash-alt"></i>
</a>
</div>
<div>
<a href="javascript:void(0)" class="text-light" uk-tooltip="title: Previsualizar"
uk-toggle="target: #modal-media-image" #click="showImage(image)">
<i class="fas fa-search-plus"></i>
</a>
</div>
</div>
</div>
<div class="details">
<span class="size" v-text="getFileSize(files[index].size)"></span>
</div>
<div id="modal-media-image" class="uk-flex-top" uk-modal>
<div class="uk-modal-dialog uk-width-auto uk-margin-auto-vertical">
<button class="uk-modal-close-outside" type="button" uk-close></button>
<img width="1024px" :src="dialogImageUrl">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer bg-opacity-7-dark">
<button type="button" #click="createPost" class="btn btn-primary float-right">
<template v-if="isCreatingPost" class="align-items-center">
<div class="d-flex align-items-center">
<span class="mr-1">Publicando</span>
<div class="loadingio-spinner-dual-ring-botj7pu8xqc">
<div class="ldio-ifliw7yncz">
<div></div>
<div>
<div></div>
</div>
</div>
</div>
</div>
</template>
<template v-else>
Publicar
</template>
</button>
</div>
</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
name: "FormPostText",
props: ['profile'],
data() {
return {
dialogImageUrl: "",
dialogVisible: false,
isDragging: false,
dragCount: 0,
files: [],
images: [],
status_msg: "",
status: "",
isCreatingPost: false,
title: "",
body: "",
isOpen: false
}
},
mounted() {
$("#content-body").emojioneArea({
placeholder: "¿Qué estás pensando?",
searchPlaceholder: "Buscar",
buttonTitle: "Usa la tecla [TAB] para insertarlos más rápido",
pickerPosition: 'bottom',
filtersPosition: "bottom",
searchPosition: "top"
});
},
methods: {
...mapActions({
create: "post/makePost"
}),
showImage(file) {
this.dialogImageUrl = file;
this.dialogVisible = true;
},
OnDragEnter(e) {
e.preventDefault();
this.dragCount++;
this.isDragging = true;
return false;
},
OnDragLeave(e) {
e.preventDefault();
this.dragCount--;
if (this.dragCount <= 0)
this.isDragging = false;
},
onInputChange(e) {
const files = e.target.files;
Array.from(files).forEach(file => this.addImage(file));
},
onDrop(e) {
e.preventDefault();
e.stopPropagation();
this.isDragging = false;
const files = e.dataTransfer.files;
Array.from(files).forEach(file => this.addImage(file));
},
addImage(file) {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.showNotification("La imágen no puede ser mayor a 2MB.");
return;
}
if (!file.type.match('image.*')) {
this.showNotification(`${file.name} no es una imágen`);
return;
}
this.files.push(file);
const img = new Image(), reader = new FileReader();
reader.onload = (e) => this.images.push(e.target.result);
reader.readAsDataURL(file);
return isLt2M;
},
removeimage: function (index) {
this.images.splice(index, 1);
},
getFileSize(size) {
const fSExt = ['Bytes', 'KB', 'MB', 'GB'];
let i = 0;
while (size > 900) {
size /= 1024;
i++;
}
return `${(Math.round(size * 100) / 100)} ${fSExt[i]}`;
},
toggle() {
this.isOpen = !this.isOpen;
},
createPost() {
var body = $("#content-body").val();
var text = emojione.toImage(body);
if (!this.validateForm()) {
return false;
}
this.isCreatingPost = true;
const formData = new FormData();
formData.append("user", this.profile.uid);
formData.append("body", text);
this.files.forEach(file => {
formData.append('images[]', file, file.name);
});
this.create(formData).then((res) => {
if (res.data.status === 0) {
this.status = code;
this.showNotification(res.data.msg);
}
document.querySelector(".emojionearea-editor").innerHTML = '';
this.isCreatingPost = false;
this.images = [];
this.files = [];
this.isOpen = false;
let post = res.data;
this.$emit("new", post);
}).catch(error => {
console.log(error)
this.isCreatingPost = false;
});
},
validateForm() {
if (!$("#content-body").val()) {
this.status = false;
this.showNotification("Debes escribir algo para publicar...");
return false;
}
return true;
},
showNotification(message) {
this.$swal.fire({
icon: 'error',
html: message
});
}
}
}
</script>
Post.vue =>
<template>
<div id="timeline">
<div v-if="authenticated.username === username || isFriend">
<FormPost :profile="profile" #new="addPostText"></FormPost>
</div>
<!--<pre>{{postsArr}}</pre>-->
<div v-if="postsCount > 0">
<div v-for="(post, index) in postsArr" :key="index">
<div class="cardbox shadow-lg bg-opacity-5-dark shd">
<div class="cardbox-heading">
<div class="dropdown float-right">
<button class="btn btn-sm btn-dark btn-circle" data-toggle="dropdown"
data-boundary="window">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu dropdown-scale dropdown-menu-right" role="dropdown">
<template v-if="post.user.id === user.uid || post.friend.id === user.uid">
<b-dropdown-item href="javascript:void(0)" #click="deletePost(post.post.id, index)">
<span class="uk-margin-small-right" uk-icon="icon: trash"></span> Eliminar
</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
</template>
<b-dropdown-item href="javascript:void(0)">
<span class="uk-margin-small-right text-danger" uk-icon="icon: warning"></span>
Reportar
</b-dropdown-item>
</div>
</div>
<div class="media m-0">
<div class="d-flex mr-3">
<a v-bind:href="post.user.username">
<img class="img-fluid rounded-circle" v-bind:src="post.friend.photo" alt="User">
</a>
</div>
<div class="media-body">
<p class="m-0"><a v-bind:href="post.friend.username">{{ '#' + post.friend.username }}</a></p>
<small><span><i
class="far fa-clock"></i> {{ since(post.post.created_at) }}</span></small>
</div>
</div>
</div>
<div class="cardbox-item">
<p class="mx-4">{{ post.post.body | setEmoji }}</p>
<div v-if="post.images.length > 0">
<!--<photo-grid
:box-height="'600px'"
:box-width="'100%'"
:boxBorder="0"
:excess-text="'+ {{count}} imágenes'"
uk-lightbox="animation: slide"
>
<img v-for="(imahe, index) in post.images" v-bind:src="`http://127.0.0.1:8000/storage/images/${post.friend.id}/${imahe.url}`" :key="index"/>
</photo-grid>-->
<ImagesGrid :images="post.images" :idFriend="post.friend.id"
uk-lightbox="animation: slide"></ImagesGrid>
</div>
</div>
<div class="cardbox-base">
<ul class="float-right">
<li><a><i class="fa fa-comments"></i></a></li>
<li><a><em class="mr-5">{{ post.comments_count || comments_count }}</em></a></li>
<li><a><i class="fa fa-share-alt"></i></a></li>
<li><a><em class="mr-3">03</em></a></li>
</ul>
<ul>
<li>
<Likes :postid="post.post.id" :user="user"></Likes>
</li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/3.jpeg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/1.jpg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/5.jpg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/2.jpg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a><span>242 Likes</span></a></li>
</ul>
</div>
<CommentsPost
#new="commentsCount"
:postid="post.post.id"
:postuserid="user.uid"
:user="user"
></CommentsPost>
</div>
</div>
<nav class="pagination-outer">
<ul class="pagination">
<li class="page-item" :class="[pagination.current_page > 1 ? '' : 'disabled']">
<a href="#" class="page-link" aria-label="Previous" #click.prevent="changePage(pagination.current_page - 1)">
<span aria-hidden="true">«</span>
</a>
</li>
<li class="page-item" v-for="page in pagesNumber" :class="[page == isActived ? 'active' : '']">
<a class="page-link" href="#" v-bind:data-hover="page" #click.prevent="changePage(page)">{{page}}</a>
</li>
<li class="page-item" :class="[pagination.current_page < pagination.last_page ? '' : 'disabled']">
<a href="#" class="page-link" aria-label="Next" #click.prevent="changePage(pagination.current_page + 1)">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<div v-else class="card bg-opacity-5-dark mb-4">
<div class="card-body">
<span class="text-light">No tiene posts aún.</span>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
var moment = require("moment");
moment.locale("es");
import {mapActions, mapGetters} from 'vuex'
import FormPost from "../Posts/FormPost";
import Likes from "../Posts/Likes";
import CommentsPost from "../Posts/CommentsPost";
import ImagesGrid from "../Posts/ImagesGrid";
export default {
name: "Posts",
props: {
username: {
type: String,
required: true
},
profile: {
type: Object,
required: true
},
user: {
type: Object,
required: true
},
isFriend: {
type: Boolean,
required: true
}
},
data() {
return {
page: 0,
offset: 4,
comments_count: ''
}
},
mounted() {
this.getPosts();
},
beforeRouteEnter(to, from, next) {
this.getPosts()
next()
},
beforeRouteUpdate(to, from, next) {
this.getPosts()
next()
},
computed: {
...mapGetters({
authenticated: "auth/authenticated",
postsArr: "post/postsLists",
pagination: "post/postsPagination",
postsCount: "post/postsCount"
}),
isActived: function() {
return this.pagination.current_page;
},
pagesNumber: function () {
if(!this.pagination.to) {
return [];
}
var from = this.pagination.current_page - this.offset;
if(from < 1) {
from = 1;
}
var to = from + (this.offset * 2);
if(to >= this.pagination.last_page) {
to = this.pagination.last_page;
}
var pagesArray = [];
while(from <= to) {
pagesArray.push(from);
from++;
}
return pagesArray;
}
},
methods: {
...mapActions({
getPostsByUser: "post/fetchPosts",
removePost: "post/deletePost",
}),
async getPosts(page) {
await this.getPostsByUser(page);
await this.$forceUpdate();
},
async addPostText(post) {
await this.postsArr.unshift(post);
await this.$forceUpdate();
await this.changePage(1);
},
since(d) {
return moment(d).fromNow();
},
commentsCount(count) {
this.comments_count = count;
},
deletePost(post, index) {
this.postsArr.splice(index, 1)
this.removePost(post)
},
changePage(page) {
this.pagination.current_page = page;
this.getPosts(page);
}
},
filters: {
setEmoji: (value) => {
var rx = /<img\s+(?=(?:[^>]*?\s)?class="[^">]*emojione)(?:[^>]*?\s)?alt="([^"]*)"[^>]*>(?:[^<]*<\/img>)?/gi;
return value.replace(rx, "$1")
}
},
components: {
FormPost,
Likes,
CommentsPost,
ImagesGrid
},
watch: {
'$route': 'getPosts'
}
ImagesGrid.vue =>
<template>
<photo-grid
:box-height="'600px'"
:box-width="'100%'"
:boxBorder="0"
:excess-text="'+ {{count}} imágenes'"
uk-lightbox="animation: slide"
>
<a :href="`http://127.0.0.1:8000/storage/images/${idFriend}/${imahe.url}`"
v-for="(imahe, index) in images"
v-bind:data-image="`http://127.0.0.1:8000/storage/images/${idFriend}/${imahe.url}`"
:key="index">
</a>
</photo-grid>
</template>
<script>
export default {
props: ['idFriend', 'images'],
watch: {
$route(to, from, next) {
this.$forceUpdate();
next()
}
}
};
</script>
Post.js =>
import axios from 'axios'
import store from './index'
export default {
namespaced: true,
state: {
posts: [],
posts_count : 0,
pagination: {
'total': 0,
'current_page': 0,
'per_page': 0,
'last_page': 0,
'from': 0,
'to': 0,
}
},
getters: {
postsLists(state) {
return state.posts;
},
postsCount(state) {
return state.posts_count
},
postsPagination(state) {
return state.pagination
}
},
mutations: {
SET_POST_COLLECTION (state, data) {
state.posts = data.posts.data ;
state.pagination = data.paginate;
state.posts_count = data.paginate.total;
}
},
actions: {
makePost({commit,dispatch}, data) {
return new Promise((resolve, reject) => {
axios.post('user/post/create', data)
.then((response) => {
dispatch("fetchPosts", 1)
resolve(response);
})
.catch((error) => {
reject(error);
});
})
},
fetchPosts({commit}, page) {
return new Promise((resolve, reject) => {
axios.get(`user/${store.state.user.profile.username}/posts?page=${page}`)
.then((response) => {
//console.log(response.data.posts.data);
commit('SET_POST_COLLECTION', response.data);
resolve(response);
})
.catch((error) => {
reject(error);
});
})
},
deletePost({commit}, id) {
return new Promise((resolve, reject) => {
let params = {'id': id};
axios.post('user/post/delete', params)
.then((response) => {
console.log(response.data)
resolve(response);
})
.catch((error) => {
reject(error);
});
})
},
createComment({commit}, comment) {
return new Promise((resolve, reject) => {
axios.post('user/post/comment/create', comment)
.then((response) => {
console.log(response.data)
resolve(response);
})
.catch((error) => {
reject(error);
});
})
}
}
}
Pagination links working fine as normal pages when I refresh the whole page but when i reload just data with ajax pagination does not loading next pages
$.ajax({
url: '{{route('apply.filters')}}',
type:'get',
data: {cities:cities,
category:category
},
success: function (data) {
// $(".contentlist").load(location.href + " .contentlist");
$('.contentlist').html(data);
},
error: function(xhr, status, errorThrown) {
console.log(xhr.responseText);
}
});
this is my controller function
public function filter(Request $request)
{
try {
set_time_limit(390);
$country=null;
if(Auth::check() && $country==null){
$country=Auth::user()->lat->country??'';
}if(Session::has('country') && $country==null){
$country=Session::get('country.0');
}
if(isset($request->cities)){
$data =[
'products' => Product::where([['category',$request->category],['country',$country??'']])->whereIn('city',$request->cities)->where('status',1)->Orderby('id','desc')->paginate(8),
];
}
if(isset($data)){
return response()->json(view('front.home.ajaxindex',$data)->render());
}else{
return redirect()->route('home');
}
} catch(\Exception $e) {
return back()->with('error',$e->getMessage());
}
}
this is my jsscroll function working normally fine but not loading data comes with ajax
$('ul.pagination').hide();
$(function() {
$('.contentlist').jscroll({
autoTrigger: true,
loadingHtml: '<img class="center-block" src="{{asset('front_assets/images/Spinner-1s-200px.gif')}}" width="100" alt="Loading..." />', // MAKE SURE THAT YOU PUT THE CORRECT IMG PATH
padding: 0,
nextSelector: '.pagination li.active + li a',
contentSelector: 'div.contentlist',
loadOnScroll: false,
callback: function() {
$('ul.pagination').remove();
$('.elements').each(function(){
var thisH = $(this).height();
if (thisH > maxHeight) {
maxHeight = thisH;
}
$(this).height(maxHeight);
});
}
});
});
this is my ajaxindex page this is new page only created for making html which is appended in the main page if data exists
#foreach($products as $product)
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12 item-cell">
<div class="listingscontent elements">
#if(\Illuminate\Support\Facades\Auth::guard('admin')->check())
<i id="{{$imgs->id??''}}" onclick="deletes('{{$product->id}}',this)" class="fa fa-close fa-lg pull-right" style="margin-left: -20px; mix-blend-mode: hard-light; color: rgb(0, 255, 255); "></i>
<a style=" position: absolute;" class="pull-left" href="{{route('edit.add',['id' => preg_replace('/-{2,}/','-',str_replace([" ", "'", "/","(",")","#","#"], '-',$product->title??'')).'-'.$product->id??''])}}"> <i class="fa fa-pencil-square-o fa-lg" style="mix-blend-mode: hard-light; color: rgb(0, 255, 255); "></i></a>
#endif
<a style="color: #ea1b25" href="{{route('details',['id' => preg_replace('/-{2,}/','-',str_replace([" ", "'", "/","(",")","#","#"], '-',$product->title??'')).'-'.$product->id??''])}}">
#if(isset($product->atachedImage))
<img class="listings" src="{{asset($product->atachedImage->path.$product->atachedImage->name??'noimage.jpg')}}" title="{{$product->title??''}}_image" alt="">
#else
<img class="listings" src="{{asset('images/noimage.jpg')}}" title="{{$product->title??''}}_image">
#endif
<h5 class="text-capitalize title" title="{{$product->title??''}}">{{str_limit($product->title??'',19)}}</h5></a>
</div>
</div>
#endforeach
{{$products->appends(request()->except('page'))->links()??''}}
I am working on a survey application with Asp.Net MVC. I have a page named Index.cshtml which has a question table and a 'Add New' button.Once button clicked, a popup is opened with jQuery. I am calling a view from controller to fill jQuery dialog named as AddOrEdit.cshtml (child page). I am adding new question and options. Question is a textfield and its options are added in editable table. Once clicked submt button Submit form event (save or update) is fired. But ajax sends twice request. One of these requests send empty object, the other sends full object. Where am I making a mistake?
According to my research, what causes this problem is that the unobtrusive validator is placed on 2 different pages. But this is not the case for me.
When I debug with chrome in f12, the initiator of one of the 2 requests 'jquery' the initiator of the other 'other' The type of one of these 2 post requests appears as 'XHR' and the type of the other is 'document'.
Index.cshtml
#{
ViewBag.Title = "Soru Listesi";
}
<h2>Soru Oluşturma</h2>
<a class="btn btn-success" style="margin-bottom: 10px"
onclick="PopupForm('#Url.Action("AddOrEdit","Question")')"><i class="fa fa-plus"></i> Yeni Soru Oluştur</a><table id="questionTable" class="table table-striped table-bordered accent-blue" style="width: 100%">
<thead>
<tr>
<th>Soru No</th>
<th>Soru Adı</th>
<th>Oluşturma Tarihi</th>
<th>Güncelleme Tarihi</th>
<th>Güncelle/Sil</th>
</tr>
</thead>
</table>
<link
href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet" />
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
rel="stylesheet" />
#section Scripts{
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>
<script>
var Popup, dataTable;
$(document).ready(function() {
dataTable = $("#questionTable").DataTable({
"ajax": {
"url": "/Question/GetData",
"type": "GET",
"datatype": "json"
},
"columnDefs": [
{ targets: 2 }
],
"scrollX": true,
"scrollY": "auto",
"columns": [
{ "data": "QuestionId" },
{ "data": "QuestionName" },
{
"data": "CreatedDate",
"render": function(data) { return getDateString(data); }
},
{
"data": "UpdatedDate",
"render": function(data) { return getDateString(data); }
},
{
"data": "QuestionId",
"render": function(data) {
return "<a class='btn btn-primary btn-sm' onclick=PopupForm('#Url.Action("AddOrEdit", "Question")/" +
data +
"')><i class='fa fa-pencil'></i> Güncelle</a><a class='btn btn-danger btn-sm' style='margin-left:5px' onclick=Delete(" +
data +
")><i class='fa fa-trash'></i> Sil</a>";
},
"orderable": false,
"searchable": false,
"width": "150px"
}
],
"language": {
"emptyTable":
"Soru bulunamadı, lütfen <b>Yeni Soru Oluştur</b> butonuna tıklayarak yeni soru oluşturunuz. "
}
});
});
function getDateString(date) {
var dateObj = new Date(parseInt(date.substr(6)));
let year = dateObj.getFullYear();
let month = (1 + dateObj.getMonth()).toString().padStart(2, '0');
let day = dateObj.getDate().toString().padStart(2, '0');
return day + '/' + month + '/' + year;
};
function PopupForm(url) {
var formDiv = $('<div/>');
$.get(url)
.done(function(response) {
formDiv.html(response);
Popup = formDiv.dialog({
autoOpen: true,
resizable: true,
title: 'Soru Detay',
modal: true,
height: 'auto',
width: '700',
close: function() {
Popup.dialog('destroy').remove();
}
});
});
}
function SubmitForm(form) {
debugger;
if (form.checkValidity() === false) {
debugger;
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
if ($(form).valid()) {
var question = {};
question.questionId = 1111;
var options = new Array();
$("#questionForm TBODY TR").each(function() {
var row = $(this);
var option = {};
option.OptionId = row.find("TD").eq(0).html();
option.OptionName = row.find("TD").eq(1).html();
options.push(option);
});
question.options = options;
question.responses = new Array();
$.ajax({
type: "POST",
url: form.action,
data: JSON.stringify(question),
success: function(data) {
if (data.success) {
debugger;
Popup.dialog('close');
dataTable.ajax.reload();
$.notify(data.message,
{
globalPosition: "top center",
className: "success",
showAnimation: "slideDown",
gap: 1000
});
}
},
error: function(req, err) {
debugger;
alert('req : ' + req + ' err : ' + err.data);
},
complete: function(data) {
alert('complete : ' + data.status);
}
});
}
}
function ResetForm(form) {
Popup.dialog('close');
return false;
}
function Delete(id) {
if (confirm('Bu soruyu silmek istediğinizden emin misiniz?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Question")/' + id,
success: function(data) {
if (data.success) {
dataTable.ajax.reload();
$.notify(data.message,
{
className: "success",
globalPosition: "top center",
title: "BAŞARILI"
})
}
}
});
}
}
</script>
}
AddOrEdit.cshtml
#using MerinosSurvey.Models
#model Questions
#{
Layout = null;
}
#using (Html.BeginForm("AddOrEdit", "Question", FormMethod.Post, new { #class = "needs-validation",
novalidate = "true", onsubmit = "return SubmitForm(this)", onreset = "return ResetForm(this)", id =
"questionForm" }))
{
<div class="form-group row">
#Html.Label("QuestionId", "Soru No", new { #class = "col-form-label col-md-3" })
<div class="col-md-9">
#Html.TextBoxFor(model => model.QuestionId, new { #readonly = "readonly", #class = "form-control" })
</div>
</div>
<div class="form-group row">
#Html.Label("QuestionName", "Soru Adı", new { #class = "col-form-label col-md-3" })
<div class="col-md-9">
#Html.EditorFor(model => model.QuestionName, new { htmlAttributes = new { #class = "form-control", required = "true" } })
<div class="valid-feedback"><i class="fa fa-check">Süpersin</i></div>
<div class="invalid-feedback "><i class="fa fa-times"></i></div>
</div>
</div>
#*<div class="form-group row">
#Html.LabelFor(model => model.CreatedDate, new { #class = "form-control-label col-md-3"})
<div class="col-md-9">
#Html.EditorFor(model => model.CreatedDate, "{0:yyyy-MM-dd}", new { htmlAttributes = new { #class = "form-control", type = "date", #readonly = "readonly",required="false" } })
</div>
</div>*#
<div class="table-wrapper form-group table-responsive-md">
<div class="table-title">
<div class="form-group row">
<div class="col-md-9">Seçenekler</div>
<div class="col-md-3">
<a class="btn btn-success add-new" style="margin-bottom: 10px"><i class="fa fa-plus"></i>Seçenek Ekle</a>
</div>
</div>
</div>
<table class="table optionTable">
<thead>
<tr>
<th scope="col">Seçenek Id</th>
<th scope="col">Seçenek Adı</th>
<th scope="col">Güncelle/Sil</th>
</tr>
</thead>
<tbody>
#*#foreach (Options options in Model.Options)
{
<tr>
<td>#options.OptionId</td>
<td>#options.OptionName</td>
<td>
<a class="add btn btn-primary btn-sm" title="Add" data-toggle="tooltip">
<i class="fa fa-check">Onayla</i></a>
<a class="edit btn btn-secondary btn-sm" title="Edit" data-toggle="tooltip"><i class="fa fa-pencil">Güncelle</i></a>
<a class="delete btn-danger btn-sm" title="Delete" data-toggle="tooltip"><i class="fa fa-trash">Sil</i></a>
</td>
</tr>
}*#
</tbody>
</table>
</div>
<div class="form-group row">
<input type="submit" value="Submit" class="btn btn-primary" id="btnSubmit" />
<input type="reset" value="Reset" class="btn btn-secondary" />
</div>
}
<script>
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
//var actions = $("table.optionTable td:last-child").html();
var actions =' <a class="add btn btn-primary btn-sm" title="Add" data-toggle="tooltip"><i
class="fa fa-check">Onayla</i></a>' + '<a class="edit btn btn-secondary btn-sm" title="Edit" data toggle="tooltip"><i class="fa fa-pencil">Güncelle</i></a>' +'<a class="delete btn-danger btn-sm" title="Delete" data-toggle="tooltip"><i class="fa fa-trash">Sil</i></a>';
// Append table with add row form on add new button click
$(".add-new").click(function () {
$(this).attr("disabled", "disabled");
var index = $("table.optionTable tbody tr:last-child").index();
var row = '<tr>' +
'<td><input type="text" class="form-control" name="optionId" id="optionId"></td>' +
'<td><input type="text" class="form-control" name="optionId" id="optionName"></td>' +
'<td>' + actions + '</td>' +
'</tr>';
$("table.optionTable").append(row);
$("table.optionTable tbody tr").eq(index + 1).find(".add, .edit").toggle();
$('[data-toggle="tooltip"]').tooltip();
});
// Add row on add button click
$(document).on("click", ".add", function () {
var empty = false;
var input = $(this).parents("tr").find('input[type="text"]');
input.each(function () {
if (!$(this).val()) {
$(this).addClass("error");
empty = true;
} else {
$(this).removeClass("error");
}
});
$(this).parents("tr").find(".error").first().focus();
if (!empty) {
input.each(function () {
$(this).parent("td").html($(this).val());
});
$(this).parents("tr").find(".add, .edit").toggle();
$(".add-new").removeAttr("disabled");
}
});
// Edit row on edit button click
$(document).on("click", ".edit", function () {
$(this).parents("tr").find("td:not(:last-child)").each(function () {
$(this).html('<input type="text" class="form-control" value="' + $(this).text() + '">');
});
$(this).parents("tr").find(".add, .edit").toggle();
$(".add-new").attr("disabled", "disabled");
});
// Delete row on delete button click
$(document).on("click", ".delete", function () {
debugger;
$(this).parents("tr").remove();
$(".add-new").removeAttr("disabled");
});
});
event.preventDefault(); move this line and place it immediately after function SubmitForm (form){
Like below:
function SubmitForm(form) {
debugger;
event.preventDefault();
if (form.checkValidity() === false) {
debugger;
event.stopPropagation();
}
form.classList.add('was-validated');
if ($(form).valid()) {
var question = {};
question.questionId = 1111;
var options = new Array();
$("#questionForm TBODY TR").each(function() {
var row = $(this);
var option = {};
option.OptionId = row.find("TD").eq(0).html();
option.OptionName = row.find("TD").eq(1).html();
options.push(option);
});
question.options = options;
question.responses = new Array();
$.ajax({
type: "POST",
url: form.action,
data: JSON.stringify(question),
success: function(data) {
if (data.success) {
debugger;
Popup.dialog('close');
dataTable.ajax.reload();
$.notify(data.message,
{
globalPosition: "top center",
className: "success",
showAnimation: "slideDown",
gap: 1000
});
}
},
error: function(req, err) {
debugger;
alert('req : ' + req + ' err : ' + err.data);
},
complete: function(data) {
alert('complete : ' + data.status);
}
});
}
}