var loaderGif = "https://www.tietennis.com/img/loaders/LoaderIcon.gif"
var processingImageUrl = '<img id="imgProcessing" src="' + loaderGif + '" />'
$(document).on("click", "input[name='PermissionID']", function() {
var PermissionCheckBox = $(this)[0];
$.ajax({
method: "POST",
url: "https://httpbin.org/post",
cache: false,
async: true,
beforeSend: function(xhr, opts) {
$(PermissionCheckBox).after(processingImageUrl);
},
success: function(result) {
$(PermissionCheckBox).parent().find('#imgProcessing').remove();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
Check me:
<input name="PermissionID" type="checkbox" value="1">
</td>
</tr>
</table>
I was actually trying to convert the jQuery code to vue.js.
I am trying to find a way if I could put the image with checkbox on click in vue.js.
I tried below code, but now sure how could I use event passed from checkbox to add image and remove it
updatePermission(roleModulePermissionID, event) {
}
Can you suggest something for this?
In Vue, you (optimally) don't directly manipulate the DOM. You manipulate the data and configure the template to react to that data according to what you need.
To create multiple rows, use v-for.
So, for instance, instead of adding and removing a "loading image", you would create an <img> whose display depended on some flag from your data, say permission.loading:
<img v-show="permission.loading" :src="loadingImg">
That way, when you set permission.loading to true, the loading image will show. When you set permission.loading to false it will hide.
Since you want to show it while the Ajax is performing, set permission.loading to true before calling the Ajax (the fetch() below) and set permission.loading to false when it completes.
Full demo below.
new Vue({
el: '#app',
data: {
loadingImg: "https://www.tietennis.com/img/loaders/LoaderIcon.gif", // for demo purposes
permissions: [{
id: 1,
label: 'Permission to Take off',
ticked: false,
loading: false,
postURL: "https://httpbin.org/post?take-off" // demo URL
},{
id: 2,
label: 'Permission to Board',
ticked: true,
loading: false,
postURL: "https://httpbin.org/post?board" // demo URL
},{
id: 3,
label: 'Permission to Land',
ticked: false,
loading: false,
postURL: "https://httpbin.org/post?land" // demo URL
}]
},
methods: {
updatePermission(permission) {
permission.loading = true; // set loading and image will be shown
fetch(permission.postURL, {method: "POST", body: {}})
.then(() => permission.loading = false); // setting to false will make it disappear
}
}
})
img { height: 17px; margin-bottom: -1px; }
<script src="https://unpkg.com/vue"></script>
<div id="app">
<table>
<tr v-for="permission in permissions">
<td>
<label>
{{ permission.label }}:
<input name="PermissionID" type="checkbox" :value="permission.id" #change="updatePermission(permission)" v-model="permission.ticked" :disabled="permission.loading">
</label>
<img v-show="permission.loading" :src="loadingImg">
</td>
</tr>
</table>
</div>
I also would add a :disabled="permission.loading" to prevent another click when it is loading.
Related
In an asp.net Core web application I'm using the Tagify component (Tagify home page & examples) for showing tags in input and textarea controls. Following an example from the link (see under: Same using custom suggestions) I have the following code:
<div class="col-auto" title="Start typing to show available tags ...">
<textarea name="tbSearch2" placeholder="Filter by tags" id="tbSearch2" class="form-control email-filter" rows="1"></textarea>
</div>
and javascript (ajax executes only once -> on page load):
var tagslist = '';
$.ajax({
'url': "Email/GetTags",
'success': function (data) {
tagslist = data;
// load tags for searching
var tagify1 = new Tagify(document.querySelector('textarea[name=tbSearch2]'), {
tagTextProp: 'name',
enforceWhitelist: true,
delimiters: null,
whitelist: tagslist,
editTags: false,
dropdown: {
mapValueTo: 'name',
searchKeys: ['name'],
maxItems: 20, // <- maximum allowed rendered suggestions
classname: 'tags-look', // <- custom classname for this dropdown, so it could be targeted
enabled: 0, // <- show suggestions on focus
closeOnSelect: false // <- do not hide the suggestions dropdown once an item has been selected
},
});
}
});
The tags work, but only when the user starts typing some text into the textarea. The dropdown does not appear immediately when Tagify control has focus (as in the example in the link in the beginning of this post).
Any ideas what I'm doing wrong?
*note: there are no errors in the browser console.
You can try to check the versions of tagifycss and js, Here is a working demo:
GetTags action:
public List<string> GetTags()
{
return new List<string>{ "A# .NET", "A# (Axiom)", "A-0 System", "A+", "A++", "ABAP", "ABC", "ABC ALGOL", "ABSET", "ABSYS", "ACC", "Accent", "Ace DASL", "ACL2", "Avicsoft", "ACT-III", "Action!", "ActionScript"};
}
js:
<script src="https://cdnjs.cloudflare.com/ajax/libs/tagify/4.3.0/tagify.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tagify/4.3.0/tagify.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script>
var tagslist = '';
$(function () {
$.ajax({
'url': "GetTags",
'success': function (data) {
tagslist = data;
// load tags for searching
var tagify1 = new Tagify(document.querySelector('textarea[name=tbSearch2]'), {
tagTextProp: 'name',
enforceWhitelist: true,
delimiters: null,
whitelist: tagslist,
editTags: false,
dropdown: {
mapValueTo: 'name',
searchKeys: ['name'],
maxItems: 20, // <- maximum allowed rendered suggestions
classname: 'tags-look', // <- custom classname for this dropdown, so it could be targeted
enabled: 0, // <- show suggestions on focus
closeOnSelect: false // <- do not hide the suggestions dropdown once an item has been selected
},
});
}
});
})
</script>
result:
I'm working on a Vue project which has a component for loading content into a modal via an ajax call:
<load-content target="foo"></load-content>
<load-content target="bar"></load-content>
<load-content target="oof"></load-content>
<load-content target="rab"></load-content>
Here's an example template:
<template>
<span class="load-content-wrapper" v-on:click="load">
Click
</span>
</template>
<script>
export default {
name: 'load content',
props: {
target: {
type: String,
required: true
}
},
methods: {
load() {
$('#load-content-modal').modal('show');
this.$store.dispatch('loadContent', this.target);
},
}
};
</script>
Which would trigger this example action:
const actions = {
loadContent ({ commit }, target) {
$.ajax({
url: '/api/fetch-content/' + target,
}).then((data) => {
// Load Modal Window
});
},
};
This all works well, except we cannot guarantee that the Ajax call will always return content. Depending on the target it could return 404.
Ideally I want to automatically disable individual load-content components if '/api/fetch-content/' + target isn't available to prevent users from trying to select unavailable content.
What is the correct/ most efficient way to do this?
You should make your "target" field not required and instead add a default value empty string.
And add an "if" condition to your load method. If "target" is empty, it will not proceed.
export default {
name: 'load content',
props: {
target: {
type: String,
default: ''
}
},
methods: {
load() {
if (!this.target) return;
$('#load-content-modal').modal('show');
this.$store.dispatch('loadContent', this.target);
},
}
};
Create a store variable loading and mutate it in your actions as follows:
loading: false
const actions = {
loadContent ({ commit }, target) {
$.ajax({
url: '/api/fetch-content/' + target,
}).then((data) => {
// Load Modal Window
commit(setLoading)
});
},
};
Then in muatations ->
setLoading (state, loading) {
state.loading = true
}
Now in your vue file use this store variable and check if it is true then load the component.You may check this created or mounted events of the component.
Option 1
Preemptively load the content, and disable the ones that return an error.
This is what the parent component will look like
<template>
<load-content
v-for="(target, index) in loadedTargets"
:key="index"
target="target"
/>
</template>
<script>
export default {
name: 'load content parent',
data: function() {
return {
targets: [
{link: 'foo', data: null, loaded: false, error: null},
{link: 'bar', data: null, loaded: false, error: null},
{link: 'oof', data: null, loaded: false, error: null},
{link: 'rab', data: null, loaded: false, error: null},
]
}
},
computed: {
loadedTargets() {
return this.targets.filter(t => t.loaded)
}
},
methods: {
load(target) {
const self = this;
$.ajax({
url: '/api/fetch-content/' + target.link,
}).then((data) => {
self.targets[indexOf(target)].data = data
self.targets[indexOf(target)].loaded = true
}).catch((error) => {
self.targets[indexOf(target)].error = error
});
},
},
mounted() {
this.targets.forEach(target => this.load(target))
}
};
</script>
Option 2
Preemptive loading is expensive (and since I don't know how many targets you might have), you could also show success/error in the modal. Proper UX would dictate that an explicit action by the user should lead to a result (i.e. if the user clicks a link, he should either see data in the modal, or an error)
This is what your action will look like:
const actions = {
loadContent ({ commit }, target) {
$.ajax({
url: '/api/fetch-content/' + target,
}).then((data) => {
// Load Modal Window
}).catch((error) => {
// Load Modal Window, and show the error
});
},
};
I am using ExpressJS to build a mangament dashboard for a community I am part of. I currently have a modal that shows up to add new games to a database. The data is fetched remotely but I am having trouble getting the data to show up to select it.
I am able to use to console.log to show the data being retrieved but I am not sure where I am falling short.
Code
$(document).ready(function () {
$('#ttitle').selectize({
create: false,
valueField: 'appid',
labelField: 'name',
searchField: 'name',
closeAfterSelect: true,
options: [],
load: function (query, callback) {
if (!query.length) return callback();
$.ajax({
url: `/games/all?search=${encodeURIComponent(query)}`,
type: 'GET',
error: function () {
callback();
},
success: function (res) {
console.log(res.value)
callback(res.value);
}
});
}
});
});
While typing in the search box, console shows the following
HTML - if it matters
<div class="form-group">
<label for="ttitle">Game Title</label>
<select name="ttitle" id="ttitle">
<option></option>
</select>
</div>
The searchField setting takes an array value (not a string), so you need to change it to:
searchField: ['name']
Otherwise, your setup looks fine.
I have page to show data using jquery and bootstrap table in laravel :
In body I have hidden type to parse value to jquery :
<input type="hidden" name="compName" id="compName" value="">
The jquery code :
<script type="text/javascript">
$(document).ready(function(){
$('#attendanceTable').bootstrapTable({
classes: 'table table-striped',
striped: true,
formatLoadingMessage: function(){ return '<img src="public/assets/images/cui-loading.gif" width="30px"/>';},
url: '{{ URL::route("get_data_attendance") }}',
queryParams:function(p){
p.iSearch = $('#iSearch').val();
p.compName = $('#compName').val();
return p;
},
pagination:true,
sidePagination:'server',
columns: [{
field:'nik',
title:'NIK',
},{
field:'date',
title:'DATE',
},{
field:'staffname',
title:'NAME',
},{
field:'in',
title:'IN',
},{
field:'out',
title:'OUT',
}]
});
$('.filterTable').on('click',function(e){
e.preventDefault();
$('#attendanceTable').bootstrapTable('refresh', {
url: 'http://portal.rodalink.com/attendance/data',
queryParams:function(p){
p.iSearch = $('#iSearch').val();
p.compName = $('#compName').val();
return p;
}
});
});
document.addEventListener("DOMContentLoaded", function(event) {
$('.filterTable').trigger('click');
});
});
The problem is : jquery cant get the compName parameter when page is loaded, but if I click search button or refresh the page jquery can get the compName parameter. How to handle this issue? Thanks!
I´m trying to bind and event inside a RowTemplate to a viewModel function, using Kendo Grid MVVM.
However, after calling kendo.bind an error is displayed in then console, and the event does not get fired, however the grid displays correctly. Here is the error:
Uncaught Error: The mouseover binding is not supported by the button element kendo.editor.js:890
I tried to change the element type inside the row template to any other thing, with same results.
Here is my html code:
<div id="content">
<div>
<div id="grid" data-role="grid" data-bind="source: ordersSource"
data-selectable="True" data-columns='["OrderID", "ShipName", "ShipCity"]' data-row-template="rowTemplate" />
</div>
</div>
<script id="rowTemplate" type="text/x-kendo-template">
<tr data-uid="#= uid #">
<td><button data-bind="mouseover: listener">#: OrderID #</button></td>
<td>#: ShipName #</td>
<td>#: ShipCity #</td>
</tr>
</script>
And here is my viewModel code:
var ordersDatasource = new kendo.data.DataSource({
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
schema: {
model: {
id: "OrderID",
fields: {
OrderID: { type: "number" },
ShipName: { type: "string" },
ShipCity: { type: "string" }
}
}
},
pageSize: 5,
});
var viewModel = kendo.observable({
ordersSource: ordersDatasource,
listener: function (e) {
alert("Event: " + e.type);
}
});
kendo.bind($('#content'), viewModel);
Here is the jsFiddle if you want to try.
The first column button should fire the event when passing the mouse over it, however it does not.
The correct syntax to bind events is:
<button data-bind="events: { mouseover: listener }">#: OrderID #</button
(updated demo)