Using ajax to dynamically load modal details - javascript

I currently have a foreach in one of my blades. I want to create a button on each entry that will prompt a modal to show with some further details. I have the modal working correctly using many different methods (I had to try multiple due to the ensuing problem) but couldn't get a small feature I wanted to work.
// this is inside the foreach. isStaff is a custom attribute.
#if(auth::check() && auth::user()->isstaff)
<span style="position: absolute;top: 0;left: 0;" class="quickview btn btn-sm btn-primary ml-3" data-toggle="modal" data-target="#modal" value="{{ $loop->index }}"> // loop used to get index of foreach
<i class="fas fa-search"></i>
</span>
#endif
I basically want to have two arrows on the top of the modal (pictured) that would either go to the previous or next entry in the foreach.
image (sorry can't embed yet)
I'm wondering how i can handle this logic? at first, I passed in the id through my controller for the specified entry the incremented and decremented it, though i cannot pass the collection through.
$(document).ready(function(e) {
$('.quickview').on('click', function(e) {
e.preventDefault();
$('#modal').find(".modal-body").load("admin/preview/" + $(this).attr('value'));
});
});
Basically, is there a way to pass either the collection through, or dynamically change the ids in the modal then showing it? I had tried a var collection = "<?php json_encode($collection); ?>"; but i could no longer use relationships.
I had also tried an ajax request where I passed in the collection but a similar problem of not having relationships occurred.
I had thought about simply making the new URLs ex. admin/preview/n +1 and n - 1, though realistically I still need the collection in order to do $collection[n] to display
Sorry for the noob-ish question, thank you for reading and for any help in advance!

Related

Unable to remove item in session jsp

I have set a list of items into the session using this piece of code
session.setAttribute("selectedList",listSelected);
Later, I wanted to remove that selectedList attribute from the session on clicked event of a button, like so
<button type="reset" style="text-align: center" onclick="function openPage(pageUrl) {
sessionStorage.removeItem('selectedList');
window.localStorage.removeItem('selectedList');
window.location.href = pageUrl;
}
openPage('/TN2_war_exploded/SupplierPage/SupplierSearch.jsp')">Cancel
</button>
Despite trying both methods, sessionStorage.removeItem and window.localStorage.removeItem, when I move back to the page, the session still holds my list and informations within are still displayed
What did I do wrong? any tip is appreciated

Stimulus: how to handle repeating items with the same target name

I have a list of items, and each one has a link to click to edit it. I am using stimulus to make the edit "modal" form visible when they click that edit link. The id of what is going to be edited is present as an id= on the corresponding link tag of the list
So, the edit link looks like this:
<td>
<a data-action="click->content#edit"
data-target="content.editBtn"
id="<%= url_for(content) %>")>
Edit
</a>
</td>
And the idea is that the content#edit action in the stimulus controller examines the and locates the id of it and uses that to edit the right row.
However the problem I am having is, I think, that as a result all the rows of this list have a data-target with the same name and the wrong one (the first one?) gets bound to the target..
However if I wanted to make each data-target different by e.g. appending the id to it, now I have a long list of targets in the controller.js so that doesn't make sense.
What's the right way to handle?
If you're using Rails as the backend like your other questions seem to indicate, there may be a simpler, non-Stimulus solution. To use Stimulus, you'd need to fetch the data for the item from the server or from the DOM, display it in a form, then submit the correct form with the correct ID to the server through JavaScript. Why not just have a remote link_to button to the edit action for each item? Rails gets a JS request to the edit controller action, and you can load the modal form with the data that you have from your Ruby object.
If you use Stimulus for anything on the form, I'd use this opportunity to craft a Stimulus controller that listens to the ajax->send/error/complete events and automatically disables/enables buttons, sets loading spinners on buttons, and closes the modal. Those would be good areas to sprinkle in some functionality that Stimulus makes very simple.
This is actually a good use of Stimulus since it is modular. You add a controller for each row instead of having the controller around the page or table.
<tr data-controller="content">
<td>
<a data-action="click->content#edit" data-target="content.editBtn" id="<%= url_for(content) %>")>
Edit
</a>
</td>
</tr>
I was just having a similar problem.
This helped:
https://codepen.io/smashingmag/pen/ExPprPG
Basically you can loop over the targets like:
for(let tgt of this.mySameNameTargets) {
tgt.innerHTML = "Some Value"
}
This assuming you have this in the controller:
state targets = ["mySameName"]
You can also use "Action Parameters" to put the id in each row:
https://stimulus.hotwired.dev/reference/actions#action-parameters
From those docs it looks like this:
<div data-controller="item spinner">
<button data-action="item#upvote spinner#start"
data-item-id-param="12345"
data-item-url-param="/votes"
data-item-payload-param='{"value":"1234567"}'
data-item-active-param="true">…</button>
</div>
// ItemController
upvote(event) {
// { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
console.log(event.params)
}
You can set the id of the item in that row in a param, and then when they click on that row you can dig it out of the params.

Need to check value of hidden input field related to clicked element (multiple with same name)

Title isn't that clear, so let me see if I can explain what I'm doing.
I'm listing off users' posts, and have a like/comment button with those posts.
What I need to do, is capture when the like button is clicked (<span> tags), and then grab the post id from the hidden input field, and use that to post to the PHP script.
The PHP is doing all of the checking for if they're friends, privacy level is correct, etc. before actually submitting the like to the database, but I am currently just having the javascript/jquery be generated when the post is shown (naming each js variable/DOM element according to post id), but that's not very efficient and looks messy when viewing the source (But, it's the only way I can get it to work).
I want to be able to use an external javascript file to check when just the like button is clicked, and know what post that is being liked, and work that way.
I've been looking into this for quite some time, and it's to my understanding that this might work, but I have had no luck. I'm generating multiple posts on one page using foreach() loop, so the names/ids/classes of the elements are the same.
For a little better understanding, here's an example of what a post might look like:
<div class="feedPost">
<img src="#" class="feedProfile"/>
FirstName LastName
<div class="feedPostBody">Hello, world!</div>
<input type="hidden" value="24772" name="feedPostID">
<span class="feedLikeButton">Like</span> | Comment | 2 mins ago
</div>
and, using javascript/jquery, I want to be able to do something like this in an external js file:
$('.feedLikeButton').on('click',function(){
var post_id = 0; //I need to get the ID from the post that the like button is related to.
//If I just did $('.feedPostID').val() it wouldn't work
$.post("https://mysite/path/to/like.php", {post: post_id}).done(function(data){
if(data == "success"){
//This will set text from "Like" to "Unlike"
//Again, I can't just do $('.feedLikeButton') to access
//I guess I could do this.innerHTML? Would still need to access feed post id
} else {
//Probably will just flash error to user if error, or something similar
}
});
});
You should get the like button
var likeButton = $(this);
Then get it's container
var container = likeButton.parent();
Then find the hidden field
var idInput = container.find('[name="feedPostID"]');
Then get it's value:
var id = idInput.val();
With all these references you can do whatever you want.

Accessing dynamic element id's in AngularJS

I am working with an app that has an ng-repeat that populates a navigation sidebar with a list of items from a Mongo DB. The ng-repeat also populates a series of option buttons for each item. A couple of these option buttons share a dynamic id for each iteration in the ng-repeat. What should be happening here is when I click on one of these buttons, it would change the button 'text' and display some additional options under the menu item and toggle back when clicked again.
Here is my code for these buttons:
<span>
<button ng-hide="highlightItem()" ng-click="showTopic()" ng-attr-id="{{ 'category' + subject._id }}" class="add-button"><i class="fa fa-chevron-down"></i></button>
<button ng-click="hideTopic()" ng-show="highlightItem()" ng-attr-id="{{ 'category' + subject._id }}" class="add-button"><i class="fa fa-chevron-up"></i></button>
</span>
The issue that I am having is that I cannot seem to figure out how to access that dynamic id in my controller. I have code in place that will change the button between the ng-show and ng-hide, but it does it for all iterations of ng-repeat.
This is currently how I am attempting to access the dynamic id. I am not getting any errors, but when I try to use this in my function it doesn't work.
$scope.subjectList = subjects.get({});
var topicButton = document.getElementById('topic' + $scope.subjectList._id);
I have also tried
var topicButton = document.getElementById('topic' + $scope.subject._id);
What is the best way to access the dynamic id in Angular/Javascript? I do not want to use jQuery with this if at all possible.
First and foremost, never manipulate the DOM within an angular controller! It is bad practice. Also, it is bad practice to evaluate methods in ngShow/ngHide.
If I understand you correctly, you're trying to get the subject_id for some reason when the button is clicked. Why can't you just pass back either the id or the entire subject to your method? Then your html would look something like this:
<span>
<button ngClick="toggleTopic(subject)" class="add-button">
<i class="fa" ng-class="{'fa-caret-down': subject.hidden, 'fa-caret-up': !subject.hidden}"></i>
</button>
</span>
Then in your controller you could write something like this:
$scope.toggleTopic = function(subject) {
subject.hidden = !subject.hidden;
};
Using the hidden attribute of your subjects, you can now show or hide elements of your dropdown with ngShow/ngHide like so:
<p ng-bind="subject.descripton" ng-hide="subject.hidden"></p>
This way, you don't have to search the DOM for elements at all.

HTML View loses state during search (ajax) update

I have been searching around trying to find a solution to this with no success :(
I have a page that lists products. The page has two layouts (list and grid) with a toggle to switch between the views (basically changing the CSS behind the view) this is all working as expected !
I am using full text search on the page containing of a search box (text input) that filters the products based on the entered search string etc... this is also working as expected.
I have a keyup event listener on the text input so that the data is filtered on each key press using an ajax get response. The data is filtered correctly however the view state / switch is not considered.
E.g. the default view is a list. If I do not change the view and search, everything is updated correctly: the correct results renders as a list. However, if I change to the grid view, and then search, although the results are correct the view is switched back to the original (list) view.
The switch toggle also stops working after a search has passed.
I am not sure, but it seems like the $.get methods response reloads the original file not containing any added classes (in relation to the view change) that have been added. It also appears that all JS added on document load is lost.
This is "basically" what I have:
CSS
.hideSection {
display: none;
}
HTML
<form accept-charset="UTF-8" action="/employees" id="employee_search" method="get">
<input autocomplete="off" id="query" name="query" type="text">
</form>
<div class="btn-group">
<button id="listViewButton" type="button" class="btn btn-default btn-sm">LIST</button>
<button id="gridViewButton" type="button" class="btn btn-default btn-sm">GRID</button>
</div>
HTML
<div id="listView" class="list-view">
...
</div>
<div id="gridView" class="grid-view hide-view" >
...
</div>
JS (CoffeScript)
$("#gridViewButton").click ->
$(".gridView").removeClass "hideSection"
$(".listView").addClass "hideSection"
$("#listViewButton").click ->
$(".listView").removeClass "hideSection"
$(".gridView").addClass "hideSection"
$("#employee_search input").keyup ->
$.get $("#employee_search").attr("action"), $("#employee_search").serialize(), null, "script"
false
As said, all searching works as expected, the problem is that the view looses its state (List or Grid) when searching, and additionally all JS appears not to work after the search - im not sure if this is something to do with the response from the $.get method as looking at it in the inspector, it contains the HTML from the original file not the modified file after changing the view etc..
Any help on this in relation to keeping the view state on searching would be greatly appreciated !
Thanks,
Jon.
listView and gridView are id not class and use toggleClass() like,
$("#gridViewButton").click ->
$("#gridView,#listView").toggleClass "hideSection"
$("#listViewButton").click ->
$("#listView,#gridView").toggleClass "hideSection"
The only way I managed to achieve my required behavior was to modify the Ajax GET method, by adding a success handler and modifying DOM data within this handler:
Within my keyup handler, before the GET, I save the current view state (styles added to the view containers) in variables accordingly. Within the GET, in the success handler I modify the result setting the view (styles) to the the new (changed) values (form the set variables) after the DOM was loaded:
$("#employee_search input").keyup (event) ->
alteredListViewHtml = $(".listViewEmployeeContainer").attr("class")
alteredGridViewHtml = $(".gridViewEmployeeContainer").attr("class")
$.get $("#employee_search").attr("action"), $("#employee_search").serialize(), ((result) ->
$(".listViewEmployeeContainer").attr('class', alteredListViewHtml)
$(".gridViewEmployeeContainer").attr('class', alteredGridViewHtml)
viewToggleClickHandlers()
return ), "script"
false
I hope this makes sense and can help someone out !
Cheers,
Jon.

Categories

Resources