Angular: get updated records after comment added - javascript

I have a post section in which user can add comments and reply. I have applied pagination logic to post section. When page loads initial 5 records of first page, I am displaying. Then I have reload button, on its click next 5 records of second page gets fetched from api and appended (concat used) to previous result like wise happens. I am calling getallpost function every time when reload button hits, when comment/reply gets added to get updated entries/data from api.
getallpost function.
getallpost() {
this.formData = new FormData();
this.formData.append("page", this.pageNumber);
this.formData.append("perpage", this.perPageRecords);
this.postService.getAllEventsPost(this.formData).subscribe((result) => {
if (result['status'] === false) {
} else {
this.totalRecords = result.data.pagination.totalRecords;
this.lastPage = result.data.pagination.LastPage;
this.selectedpost = this.selectedpost.concat((result as any).data.data);
this.selectedpost.map((item) => {
item.show = false;
item.isReadMore = true;
item.isShow = true;
});
}
});
}
pageNumber = 1 , perPageRecords = 5 , selectedpost = [] are defined.
on Relaod button click function is as follows.
onReloadbuttonClick() {
this.pageNumber++;
this.getallpost();
}
When comment/reply gets added function is like below
onSubmit(post_id) {
this.loading = true;
if (this.f.comment.value) {
this.postService
.addPostComment(this.id, post_id, this.f.comment.value)
.subscribe((data) => {
if (data['message'] === 'Token is Expired') {
this.loading = false;
this.authService.logout();
} else {
if (data['status'] === false) {
if (data['errors']) {
console.log(data['errors'][0].comment);
}
this.loading = false;
} else {
this.form.reset();
this.getallpost();
this.notifyService.showSuccess(
'Comment added successfully!!',
''
);
this.loading = false;
}
}
});
} else {
this.notifyService.showWarning('Please enter the comment.', '');
this.loading = false;
return;
}
}
Reload button works as expected. The problem I am facing is when I add comment/reply it gets added and success message gets displayed. But the comment I added not gets shown at that point even if I am calling getallpost function.
Its because of this.selectedpost = this.selectedpost.concat((result as any).data.data); this line current page number value new updated data gets fetched and appended again and not get replaced with new updated data. Means e.g. initially there are 5 records of first page fetched. After comment added to one of the post then getallpost function gets called and 5 records of first page gets called again having respective updated post with comment added. Ideally only data should get updated and should not get appended.
Which logic should I apply to get updated records in this.selectedpost after comment/reply added in above case without reloading/refreshing page (like without using location.reload etc)?
I have tried some logics but those are not working as expected with reload button.
Please guide and help. Thanks.

I am not sure whether I understood your problem statement properly or not.
Let me know if something is not making sense.
new updated data gets fetched and appended again and not get replaced with new updated data.
Just set selectedpost = [] each time you click on reload or before calling getAllPost() or inside of getAllPost() before assigning.
Which logic should I apply to get updated records in this.selectedpost after comment/reply added in above case without reloading/refreshing page
Call getAllPost inside onSubmit after successful addition of comment to avoid reload/refresh
} else {
this.form.reset();
this.getallpost(); // You are already doing this.
this.notifyService.showSuccess(
'Comment added successfully!!',
''
);
There will be a delay obviously in getting updated details from DB using API. Hence you can show the spinner at the comment section level and populate as soon as you get the details.
I am assuming your API returns a proper response after adding comments.

Related

Why my modal doesn't render correct event information after updating any event on fullcalendar

I'm using Fullcalendar Js (5.6) and laravel lilvewire on a laravel application (8.75).
I create a calendar and display some events on it. I make a modal which opened when I click on an event. This modal contains a form with filled inputs with event informations.
Here it's how I render the form with filled inputs :
eventClick: info => {
info.jsEvent.preventDefault();
let modal = document.getElementById('modal')
let deleteBtn = modal.querySelector('#delete')
if(deleteBtn.hasAttribute('hidden')) {
deleteBtn.removeAttribute('hidden')
}
if(info.event.extendedProps.report) {
deleteBtn.setAttribute('disabled', '')
} else {
deleteBtn.removeAttribute('disabled')
}
modal.querySelector('#modal-title').innerText = 'Modify an event'
modal.querySelector('input[id="title"]').setAttribute('value', info.event.title)
if(info.event.extendedProps.description != null) {
modal.querySelector('input[id="description"]').setAttribute('value', info.event.extendedProps.description)
}
modal.querySelector('input[id="start"]').setAttribute('value', (new Date((info.event.start).toString().split('GMT')[0]+' UTC').toISOString()).substr(0,23))
if(info.event.allDay) {
modal.querySelector('input[id="allDay"]').setAttribute('checked', true)
}
}
When I submit my form to update the title for example ("newTitle"), I can see changes on the calendar view but if I clicked again on the event I've changed, title input is empty (other datas are correct and well displayed on the inputs). If I clicked on another event that is not modified I have the same issue, empty title and other datas correct and well displayed.
I logged :
infos.event.title
-> result : newTitle
-> The new title is correct on the event informations
modal.querySelector('input[id="title"]')
-> result : <input id="title" type="text" value="newTitle">
-> The DOM input element has the correct value
modal.querySelector('input[id="title"]').value.length
-> result : 0
-> It's weird that the length of value is zero??
It was an example with title but I have the same weird behavior with the other inputs if I modify them.
Here is my Calendar component where I get events :
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Event;
use App\Models\Client;
use Illuminate\Support\Arr;
class Calendar extends Component
{
public $events = [];
public $clients = [];
public function mount($events)
{
$this->events = json_encode($events);
}
public function render()
{
return view('livewire.calendar');
}
public function eventUpdate($event)
{
$e = Event::find($event['id']);
$e->title = $event['title'];
$e->description = $event['description'];
$e->start = $event['start'];
$e->end = $event['end'];
$e->allDay = $event['allDay'];
if($e->isDirty()) {
$e->update($event);
}
}
}
I've already try to get the events on the render method and call #this.render() after submitting the form but it's still the same.
If I reload the page after submitting, all is correct, title is well displayed even on the calendar view than into the modal when I clicked on it.
Does anyone can see the issue that can cause this on my code?
Thanks a lot

How can i execute a function after a form submission causes a page refresh?

I am using shopify's built in customer create, login, reset form submissions which on submit, forces the page to refresh. My intention is to show a message that shows after the page has been refreshed via a button click function. This is what i have so far; The message shows until that page refreshes and then the active class is removed as you would expect.
$(document).ready(function () {
class Alert {
constructor() {
this.customerAlert = document.createElement('div');
}
init(){
this.customerAlert.classList.add('customer-alert');
document.querySelector('body').append(this.customerAlert);
}
show(message){
this.customerAlert.textContent = message;
this.customerAlert.classList.add('active');
setTimeout(() => {
this.customerAlert.classList.remove('active');
}, 8000);
}
}
//create snackbar and initiate
const alertMessage = new Alert();
alertMessage.init();
const createAccountButton = document.querySelector('input.account-trigger');
createAccountButton.addEventListener('click', () => {
alertMessage.show('Your account in now under review');
});
});
Set a boolean variable in session storage just prior to the submit to represent the two states, and then read it in after the refresh.
Something like this:
function HandleFlag(){
var F=sessionStorage.getItem('Flag');
if(F=='1'){
// display your message box here
sessionStorage.setItem('Flag','0');
} else {
// the state is "0" so toggle it just before submitting
sessionStorage.setItem('Flag','1');
}
}
I hope you get my drift.

i have problem in ajax Post not display data

i have table with search fields seprated to
1- table header contain "search fields - table headers"
2- table body => come from ajax post method
3- pagination => come from ajax post method after data excuted "i used setTimeout to delay this function"
the data display automaticly in the table body by ajax post & if the user use search fields also the data filterd by search words and pagingation also display basd on data
i have 2 cases
1- in the main page the table loaded with the page and evry thing working fine i used the follwing function:
follwing function responsible for data
jsQueryDataLive(defaultPageNo);
function jsQueryDataLive(defaultPageNo){
var objData = {
action : dataTableName +'/QueryData',
ajaxClass : actionSplit0,
ajaxPage : defaultPageNo,
};
$('#form-query-main').find(":input").each(function(){
objData[this.name] = $(this).val();
});
// console.log(objData);
// NOTE: the below line is Responsible for determining the location we need to view data on
var locationID = '#main-table-tbody';
ajaxPost(objData, locationID);
}
the following function for pagination
jsPaginationLive(defaultPageNo);
function jsPaginationLive(defaultPageNo){
setTimeout(function () {
var objData = {
action : dataTableName +'/Pagination',
ajaxClass : actionSplit0,
ajaxPage : defaultPageNo,
};
// document.getElementById("jsData").innerHTML =JSON.stringify(objData);
// NOTE: the below line is Responsible for determining the location we need to view data on
var locationID = '#pagination';
ajaxPost(objData, locationID);
}, 100);
}
i used the following function for filter
$('.searchField').keyup(function() {
jsPageNo(defaultPageNo);
} );
function jsPageNo(defaultPageNo) {
jsQueryDataLive(defaultPageNo);
jsPaginationLive(defaultPageNo);
}
2- the second case is when i want to display the obove bage in the modal
as you see in the page the table and data display correctly
i used this function to define table and load the main bag :
var dataTableName;
jsDataTableName();
function jsDataTableName(tableName) {
if (tableName === undefined) {
dataTableName = actionSplit0;
// console.log(dataTableName);
}
else {
dataTableName = tableName;
console.log(dataTableName);
// NOTE: load External Class Query page
jsLoadExternalClass();
}
}
function jsLoadExternalClass(){
var objData = {
action : dataTableName +'/Query',
ajaxClass : actionSplit0,
ajaxPage : defaultPageNo,
};
// document.getElementById("jsData").innerHTML =JSON.stringify(objData);
// jsPaginationLive(defaultPageNo);
// NOTE: the below line is Responsible for determining the location we need to view data on
var locationID = '#externalClass1';
ajaxPost(objData, locationID);
jsPageNo(defaultPageNo);
}
the problem with me in filtered not working when i type imediatly but it work after i close the modal and re open it again
enter image description here
also if there is a better solution to start function jsPaginationLive after jsQueryDataLive finished instead of setTimeout please let me know
If you set the timer on setTimeout from 100 ms to 2,000, does it still have the issue? One of the problems I've run into when using timeouts to handle situations like these is that any variance in the loading times of the site (which can always vary for any number of reasons) can cause your timeout to fail to achieve your goal.
So instead I'd suggest this: either add a variable which is set by the data function upon completion or you could use a value in the data function which must not be undefined before proceeding, then have the pagination function in a setInterval, like this:
var interval;
interval = setInterval(function(){
if (dataHasLoaded){ // This will be whatever the you decide to name the variable
jsPaginationLive(defaultPageNo);
clearInterval(interval);
}
},500);
This will ensure that the pagination function will never attempt to load before the data has been fully loaded.
EDIT: Alternatively, you can place "jsPaginationLive(defaultPageNo);" somewhere at the end of "jsQueryDataLive(defaultPageNo);" so it won't attempt pagination until the data function has completed.
Answer to 2nd question:
If you want to only run an interval while a user is typing, you can do something like this:
var interval;
window.onkeydown = function(){
clearInterval(interval);
interval = setInterval(function(){
if (dataHasLoaded){
jsPaginationLive(defaultPageNo);
clearInterval(interval);
}
},500);
}
var keyTimeout;
window.onkeyup = function(){
clearTimeout(keyTimeout);
keyTimeout = setTimeout(function(){
clearInterval(interval);
}, 5000); // The interval will be cleared 5 seconds after the last keypress. Change as needed.
}
I feel like there's a cleaner way to do this, though. Why do you want the interval to only be active during typing?

How to handle Promises in do...while loop in Protractor

it('AddnewSupplier1',function() {
var i =0;
var isenabled=false;
var count=0;
element(by.css("path[d*='M20.995']")).click();
element(by.cssContainingText('div[class="mat-step-text-label ng-star-inserted"]','Supplier Maintenance')).getText().then(function(text) {
console.log(text);
}).then(function() {
do {
if (i>0) {
console.log("Clicking on NextButton");
element(by.css("button[class='mat-paginator-navigation-next mat-icon-button']")).click();
}
(element.all(by.xpath("//table[#class='mat-table']/tbody/tr/td[1]"))).each(function(webelement) {
webelement.getText().then(function(text) {
if(text=="IACE") {
count++;
console.log("Element is found");
//break;
}
});
});
var nextbutton = element(by.css("button[aria-label='Next page']"));
nextbutton.isEnabled().then(function(isEnabled) {
var isenabled=isEnabled;
console.log(isenabled);
}).then(function() {
i++;
console.log(i);
});
}
while(isenabled);
})
});
I have to check if Supplier ID "IACE" is present in the table.
For that I have written code taking all the values in the first column of the table and check using "each".
If the element is present in the first page the code works. But if it is in second page or third then I have to click on the next button. Before clicking on the next button I need to check if the button is enabled or disabled. If the button is enabled, then I click on the next button and check if the element is present in that page and so on. If the button is disabled, then it means element is not present and I have to fail the testcase.
For this I have written code below. I have used Do ...while because i the first page it has to check without condition (i.e next button is enabled or not).
The issue happening is:
I have stored the isEnabled() value in isenabled variable.I have initialised this variable to false.
But when I run the testcase, though my value is in second page, it is not going to second page. Instead it checks in the first page and stops the test. This is happening because in while(isenabled), isenabled is stored as false. I think before executing the isEnabled() function while(isenabled) is getting executed. Therefor while(isenabled) is getting false value which is initialised value.
I am unable to find where and how to resolve the promise here.
I tried adding async and await ,But when i add these it shows error (red cross mark).Di need to import anything before i add these async and await to my protractor scripts. I have done (SELENIUM_PROMISE_MANAGER: false, ) this in my configuration file.What else i need to do other than this to add async and await.
Still not sure what it is you are trying to accomplish but resolving the promise should work if you change your code like this:
}).then(async function() { //add async
do {
// your code here up until var nextbutton = see next line
var nextbutton = element(by.css("button[aria-label='Next page']"));
isenabled = await nextbutton.isEnabled(); // await isEnabled and store result in isenabled variable
console.log(isenabled);
i++;
console.log(i);
}
while(isenabled);
if you can't use async/await you could also do the following:
.then(function() {
function repeatMe() { // replace do with a function
if (i>0) {
console.log("Clicking on NextButton");
element(by.css("button[class='mat-paginator-navigation-next mat-icon-button']")).click();
}
(element.all(by.xpath("//table[#class='mat-table']/tbody/tr/td[1]"))).each(function(webelement) {
webelement.getText().then(function(text) {
if(text=="IACE") {
count++;
console.log("Element is found");
//break;
}
});
});
var nextbutton = element(by.css("button[aria-label='Next page']"));
nextbutton.isEnabled().then(function(isEnabled) {
console.log(isEnabled); // no need for isenabled variable anymore
i++;
console.log(i);
if (isEnabled) {
repeatMe(); // call repeatMe if isEnabled is true
}
});
}
repeatMe(); // replace while with calling function repeatMe once
})

Fill TextBox with data on page load using javascript

I'm working with a Google-Extention which allows me to open a new tab containing a form. After the form gets filled out and saved, every time I open this tab again the form should be prefilled with the data saved earlier.
Here is how the data gets saved: WORKS!
function saveCheckoutData() {
var vName = document.getElementById('txbx_name').value;
chrome.storage.sync.set({'name': vName}, function() {
console.log(vName);
})
}
Here is how i get the data: WORKS!
function getdata() {
chrome.storage.sync.get('name', function(data) {
var name = data.name;
if(name != null){
document.getElementById("txbx_name").value = name;
}
});
}
The code above gets called on button click and works perfectly!
But as soon I try to do this when the tab gets opened it doesn't work (the tab gets opened but there is nothing in the textbox): DOESN'T WORK!
function configAutofill(){
var newURL = "autofill_data.html";
chrome.tabs.create({ url: newURL });
chrome.storage.sync.get('name', function(data) {
var name = data.name;
if(name != null){
document.getElementById("txbx_name").value = name;
}
});
}
Does some one have an Idea why these lines do not work when creating a new tab?
Many thanks in advance.
Here's a question for you.
After creating a new tab, you access document.getElementById. Yes, but which document?
In your case, it would be the page calling create - which is not the created page.
In your case, it seems like you're opening a page that's part of the extension. Then you should just include code in it that will run on load.
You may want to check document.readyState:
if (document.readyState === "loading") {
document.addEventListener('DOMContentLoaded', getdata);
} else {
getdata();
}
If you're trying to do this with a webpage, you'll need a content script. Again, those normally execute after DOM is parsed - so just call getdata() at top level.

Categories

Resources