Sweetalert2 is it possible to display the alert only once? - html

I have a question. Is it possible for sweetalert2 to appear only once per page?
So that it would remember that it had already displayed the alert once.
Swal.fire({
title: 'Do you want to save the changes?',
showDenyButton: true,
showCancelButton: true,
confirmButtonText: `Save`,
denyButtonText: `Don't save`,
}).then((result) => {
/* Read more about isConfirmed, isDenied below */
if (result.isConfirmed) {
Swal.fire('Saved!', '', 'success');
} else if (result.isDenied) {
Swal.fire('Changes are not saved', '', 'info');
}
});
<script src="//cdn.jsdelivr.net/npm/sweetalert2#11"></script>

The sweetalert library doesn't have specific functionality for this, so it will need to be written by yourself. Below is an example of how you could make it work to only have the alert open once.
// Add this variable in a place where it will persist (like the component or service)
hasAlertOpened = false;
// Add this in the function where the Swal.fire is executed
if (this.hasAlertOpened) {
// Prevent continueing if the alert has opened before
return;
}
Swal.fire({
title: 'Do you want to save the changes?',
showDenyButton: true, showCancelButton: true,
confirmButtonText: `Save`,
denyButtonText: `Don't save`,
}).then((result) => {
// Once it gets here we set the value to true, so it will not get here again unless you set hasAlertOpened to false somewhere else
this.hasAlertOpened = true;
/* Read more about isConfirmed, isDenied below */
if (result.isConfirmed) {
Swal.fire('Saved!', '', 'success')
} else if (result.isDenied) {
Swal.fire('Changes are not saved', '', 'info')
}
});

Related

Remove detailPanel based in condition causes padding

Everyone, I'm trying to add detailPanel based in a condition, it leaves a space when I hide it like this
Link
And This Code works fine when I provide detail panel
get rowDetailsPanel() {
const { detailPanel, classes } = this.props;
// #Workarround To Hide Details Panel In Case There is No Details Panels Provided
return [
{
tooltip: 'Show Name',
disabled: !detailPanel,
icon: () => <ChevronRightIcon className={!detailPanel && classes.displayNone}/>,
render: rowData => detailPanel(rowData)
},
];
}
Link for working detailPanel,
So what I'm trying to do is when I hide the detailPanel, I want to delete the whole column
Any clue will be appreciated
This should work:
get rowDetailsPanel() {
const { detailPanel, classes } = this.props;
// #Workarround To Hide Details Panel In Case There is No Details Panels Provided
return detailPanel ? [
{
tooltip: 'Show Name',
disabled: !detailPanel,
icon: () => <ChevronRightIcon className={!detailPanel && classes.displayNone}/>,
render: rowData => detailPanel(rowData)
},
] : undefined;

how can I update the number of columns in angular-datatables with server-side rendering. version 6.0.0 or higher

I am having trouble getting my angular-datatable to show a new column list after a rerender. I have followed the example shown in the docs for rerendering and I can get the table to rerender. I am able to manipulate certain features like searching and pageLength, but for some reason I cannot get my columns to change.
I have a very deep data set that would make my table look awful if I rendered all the columns at once, so I would like to give users the ability to select which columns they see.
I would even be open to loading in all the columns at once and just switching visibility off and on, but I cannot effect visibility either.
Has anyone had this issue before?
Rerender function:
rerender(): void {
this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.destroy();
// these work
this.dtOptions.searching = true;
this.dtOptions.pageLength = 2;
// these do not
this.dtOptions.columns = newColumnList;
this.dtOptions.columns[some-index].visible = false;
this.dtTrigger.next();
});}
Initial dtOptions:
this.dtOptions = {
searching: false,
pagingType: 'full_numbers',
pageLength: 10,
retrieve: true,
serverSide: true,
processing: true,
language: {
zeroRecords: 'Nothing Found'
},
ajax: (dataTablesParameters: any, callback) => {
const payload = this.passFilterService.processPagination(this.filter, dataTablesParameters);
this.http
.post<any>(
environment.api + '/things/list',
{payload: payload}, {}
).subscribe(resp => {
if (resp.data.data === null) {
resp.data.data = 0;
}
callback({
recordsFiltered: resp.data.totalCount,
data: resp.data.data,
recordsTotal: resp.data.totalCount
});
});
},
columns: this.tableColumns
};
Initial Columns (limited fields):
tableColumns = [
{
title: 'Customer',
data: 'Id',
render: function(data) {
return `Action`;
}
}, {
title: 'Created',
data: 'createdAt',
orderable: true,
visible: true,
}, {
title: 'Updated',
data: 'updatedAt',
orderable: true,
visible: true,
}, {
title: 'Disabled',
data: 'isVoided',
orderable: true,
visible: true,
}
];
Table implementation:
<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover">
</table>
I faced the same issue, spent hours debugging it until I found something that worked for me. I will advice separating the DT config into an independent object that can be loaded separately. Once you update your DT options and any other config, you can use the functions below to reload the entire DT, destroying and reloading it accordingly;
async rerender(newSettings?: DataTables.Settings) {
try {
this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
if (newSettings) {
// FIX To ensure that the DT doesn't break when we don't get columns
if (newSettings.columns && newSettings.columns.length > 1) {
dtInstance.destroy();
this.dtOptions = Promise.resolve(newSettings);
this.displayTable(this.dtTableElement);
}
}
});
} catch (error) {
console.log(`DT Rerender Exception: ${error}`);
}
return Promise.resolve(null);
}
This function calls the below one to actually destroy the DT and rerender it.
private displayTable(renderIn: ElementRef): void {
this.dtElement.dtInstance = new Promise((resolve, reject) => {
Promise.resolve(this.dtOptions).then(dtOptions => {
// Using setTimeout as a "hack" to be "part" of NgZone
setTimeout(() => {
$(renderIn.nativeElement).empty();
var dt = $(renderIn.nativeElement).DataTable(dtOptions);
// this.dtTrigger.next();
resolve(dt);
});
}).catch(error => reject(error));
});
}
I removed the dtTrigger execution from the reconstruction function as this was executing twice.
The dtTableElement is defined as #ViewChild('dtTableElement') dtTableElement: ElementRef; where the HTML contains the respective reference on the datatable as:
<table #dtTableElement datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table table-striped row-border hover" width="100%"></table>

How to restrict Google Maps search results to only one country properly?

I am developing an application, in Ionic, where you can plan a trip with a start address and and end address. However I want to limit this feature to only one country. Before writing I have been searching for solutions on the internet, but none of them worked for me.
Have tried these suggestions:
https://stackoverflow.com/a/8282093/8130808
https://stackoverflow.com/a/10170421/8130808
Here is how I have tried to approach it:
//Places markers and displays a route, so the user can accept the current placing
newRoutePlaceMarks(place: any): void {
var googleDiplay = new google.maps.DirectionsRenderer({ draggable: true });
var route = this.directionsDisplay;
//A bit of a hack, sadly Typescript and google maps arent the best of buddies
this.directionsService.route({
origin: this.routeStart,
destination: this.routeEnd,
travelMode: 'DRIVING',
}, function (response, status) {
if (status === 'OK') {
console.log("status is OK trying to put directions up");
//The reason why I've set the addListener before the actual route is so it gets triggered
//on the creation of the route. Had some problem with figuring out how to actually handle
//the data when on the route creation, as this response function is in strict mode, and outside
google.maps.event.addListener(route, "directions_changed", function () {
console.log("Route changed");
this.global = ShareService.getInstance();
this.directions = route.getDirections();
this.metersToDist = this.directions.routes[0].legs[0].distance.value;
this.timeToDist = this.directions.routes[0].legs[0].duration.value;
this.startAddress = this.directions.routes[0].legs[0].start_address;
this.startCord = this.directions.routes[0].legs[0].start_location;
this.endAddress = this.directions.routes[0].legs[0].end_address;
this.endCord = this.directions.routes[0].legs[0].end_location;
this.global.setMetersToDist(this.metersToDist);
this.global.setTimeToDist(this.timeToDist);
this.global.setStartAddress(this.startAddress);
this.global.setStartCord(this.startCord);
this.global.setEndAddress(this.endAddress);
this.global.setEndCord(this.endCord);
var options = {
types: ['geocode'],
componentRestrictions: { country: "dk" }
};
google.maps.places.Autocomplete(this.startAddress, options);
});
//The actual initialiser for the route
route.setDirections(response);
} else {
alert('Could not display route ' + status);
}
});
}
My problem is that the input is HTTPELEMENT, I get the input from an alert dialog
newRouteInput() {
let alert = this.alertCtrl.create({
title: 'New route',
inputs: [
{
name: 'routeStart',
placeholder: 'Start of route'
},
{
name: 'routeEnd',
placeholder: 'End of route'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: data => {
console.log('Cancel clicked');
}
},
{
text: 'Debug start and end',
handler: data => {
if (data.username !== "undefined") {
console.log(data.routeStart + " " + data.routeEnd);
this.routeStart = "Brøndby Strand";
this.routeEnd = "Hvidovre";
this.newRoutePlaceMarks(this.map);
this.routeButton = false;
} else {
return false;
}
}
},
{
text: 'Place route markers',
handler: data => {
if (data.username !== "undefined") {
this.routeStart = data.routeStart;
this.routeEnd = data.routeEnd;
this.newRoutePlaceMarks(this.map);
this.routeButton = false;
} else {
console.log(data.routeStart + " " + data.routeEnd);
return false;
}
}
}
]
});
alert.present();
}
When I run this I get an error because of this.startAddress. It's not null, it contains the start address:
InvalidValueError: not an instance of HTMLInputElement

Extjs4 Button rednerer in grid dom is null error

i am facing a problem which i want to generate a button in grid column by using reconfigure function.
i find my code consist of the Extjs error during renderer function 'Uncaught TypeError: Cannot read property 'dom' of null'
i checked that it should be come from "renderTo: id3", do you have any idea on it? Do i do something wrong in my render button function in the grid?
Although i pop up error message, but the UI still can show the button i genereated. it is very confused.
var createColumns = function (json) {
var keys = getKeysFromJson(json[0]);
return keys.map(function (field) {
if(field!='unread'&&field!='linkerType'&&field!='linkParam'&&field!='refNumber'&&field!='oid'&&field!='refOwner'){
return {
text: Ext.String.capitalize(field),
//flex : 1,
dataIndex: field,
sortable: true,
menuDisabled: true,
renderer: function (val, metadata, record) {
if(field=='action') {
var str = val.split(":");
metadata.style = "text-align: left";
if(str[2]=='true'&&str[1]=='false'){
var id3 = Ext.id();
Ext.defer(function () {
Ext.widget('button', {
renderTo: id3,
margin: '0 0 0 10',
iconAlign: 'center',
tooltip:'Ok to Ship Again',
cls: 'x-btn-default-small',
text: '<img src="images/OKToShipAgain.png">',
handler: function() {
items=[];
items.push({
"oid" : record.get('oid'),
"refNumber" : record.get('refNumber'),
"refOwner" : record.get('refOwner')
});
Ext.Ajax.request({
url: '#{csMenuBean.contextPath}/ws3/todolistservice/submitOktoship',
params: {data: Ext.encode(items)},
success : function(response){
}
});
}
})
}, 50);
return Ext.String.format('<span id="{0}"></span>', id3);
}

Proper JSON date time syntax for fullcalendar

need some help for the proper syntax for display the event times in agenda view. The events only shows up under all day despite having allDay set to false.
My json.html page looks like this:
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
eventSources: [
{
url: 'json-events.php', // use the `url` property
color: 'yellow', // an option!
textColor: 'black', // an option!
editable: false
},
// Dont forget coma - but not on the last one
{
url: 'other-events.php', // use the `url` property
color: 'red',
textColor: 'black',
editable: 'false',
allDay: 'false'
}
// any other sources...
]
});
});
One of the php pages looks like this:
<?php
echo json_encode(array(
array(
'id' => 112,
'title' => "What is this?",
'start' => "2011-10-11T13:00:00",
'end' => "2011-10-12T15:00:00",
'allDay' => "false"
),
));
?>
How do I get the events to display in the week and day agend view with the proper time (instead of being listed under the "all day" section)?
Thanks,
Extreme Newbie
After tweaking the code, I got it to work by removing the "" around false. The php page should look like this:
'allDay' => false
:)
You need to take the quotation off of "false". "false" is a string, and false is the correct "bool" false.
Also, your json call should have a query such as...
$sql = mysql_query("query") or die(mysql_error());
Followed by a while statement to retrieve the information...
while($arr = mysql_fetch_array($sql)){
$array_content[] = $arr;
}
Then encode...
echo json_encode($array_content);
This will render whatever data you have in the database.
A simple if statement within the while statement will change the string to a bool like so...
if($arr['allDay'] === "true"){
$arr['allDay'] = true;
} else {
$arr['allDay'] = false;
}
}
Hope this helps!