Retain Query String In URL - query-string

I've built a web app that lives on SharePoint.
The user is asked a question at the beginning. They can answer either "Yes" or "No."
A query string is added to the URL depending on the user's answer. So there will only be two query strings: ?choice=yes or ?choice=no.
The index.html page has this:
<input type="button" value="Yes" onclick="redirect(this);" id="yes" class="btn btn-primary btn-lg">
<input type="button" value="No" onclick="redirect(this);" id="no" class="btn btn-primary btn-lg">
And this is how the query string is initially added:
function redirect(e){
location.href = "map.html?choice=" + e.id;
}
After the user picks an answer it takes them to map.html, which is the first section the user comes into from the question (so the URL at this point can be either map.html?choice=yes or map.html?choice=no). After that, they can navigate to where ever they please on the app.
Here's the issue. The navigation is being pulled in from an external nav.js file (i.e. js include) like so:
<script type="text/javascript" src="/js/nav.js"></script>
Here's the nav.js code:
document.write(
' <div class="row text-center navigation">' +
' <ul class="nav nav-pills">' +
' <li id="nav-welcome"><a class="align" href="index.html">WELCOME</a></li>' +
' <li id="nav-map"><span>MAP</span></li>' +
' <li id="nav-about"><span>ABOUT</span></li>' +
' <li id="nav-contact"><span>CONTACT</span></li>' +
' <li id="nav-pricing"><span>PRICING</span></li>' +
' </ul>' +
' </div>'
);
How do I continue to pass either query string as the user continues to navigate the app?
There is a single page who's content will change depending on the query string.
So if the user answers "yes" at the beginning and eventually navigates to the pricing page, it will pull content specific to the "yes" answer (i.e. call a specific function).
If the user answers "no" at the beginning and eventually navigates to the pricing page, it will pull content specific to the "no" answer (i.e. call a specific function).
Thank you all in advance.

Related

Keep Filter from HttpPost on next page of PaginatedList in ASP.NET Core MVC

I am creating a program in which I have a Database with records I want to filter.
The filter has 4 input type="text" and returns the right records based on the filters I typed.
The problem is, when I click Next Page link (of PaginatedList), the second page has no filters adapted.
It lose the filters I gave. I know I must give asp-route on Next Page link some variable with the data given in filter like Microsoft Tutorial gives currentFilter, but I have 4 filters like this :
Name=x&Phone=y&...
Here is my Controller Code simplyfied :
public async Task<IActionResult> Index( some variables ){
var appusers = from a in _context.AppUsers
select a;
return(return View(await app.PaginatedList<AppUser>.CreateAsync(appusers.AsNoTracking(), pageNumber ?? 1, pageSize));)
}
AND
[HttpPost]
public async Task<IActionResult> Index(string Name, string Phone, string Calls, string Date){
var ap = from c in _context.AppUsers
select c;
Filter The database based on variable values Name,Phone,Calls,Date
return View(await PushNotificationApp.PaginatedList<AppUser>.CreateAsync(ap.AsNoTracking(),
pageNumber?? 1, pageSize));}
Here is the part of Index :
#using (Html.BeginForm("Index", "AppUsers", new { id = "filterForm" }))
{
name="SearchTrips" value="#ViewData["CurrentTrips"]" />
<input id="NameFilterField" type="text" name="Name" />
<input id="PhoneFilterField" type="text" name="Phone" />
<input id="CallsFilterField" type="text" name="Calls" />
<input id="DateFilterField" type="text" pattern="\d{1,2}/\d{1,2}/\d{4}" name="Date" />
<button class="m-3" type="submit" value="submit">Search</button>
}
AND PAGELIST LINK PART :
<div class="p-2 bd-highlight">
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item">
<a class="page-link MainButton" asp-action="Index"
asp-route-pageNumber="#(Model.PageIndex - 1)"
asp-route-currentFilter="#ViewData["CurrentFilter"]"
class="page-link #prevDisabled">
Previous
</a>
</li>
<li class="page-item">
<a class="page-link MainButton" asp-action="Index"
asp-route-pageNumber="#(Model.PageIndex + 1)"
asp-route-currentFilter="#ViewData["CurrentFilter"]"
Next
</a>
</li>
</ul>
</nav>
</div>
The problem is, when I click Next Page link (of PaginatedList), the second page has no filters adapted. It lose the filters I gave.
You are doing the filter in the Post action, but when you click the Next link, it will go to the Get action which not filter. So, I think you can make the form do a get request and just do the filter in the Get method.
I know I must give asp-route on Next Page link some variable with the data given in filter like Microsoft Tutorial gives currentFilter, but I have 4 filters like this : Name=x&Phone=y&...
4 filters is the same, just give the other filter parameters to the Next link
<a class="page-link MainButton" asp-action="Index"
asp-route-pageNumber="#(Model.PageIndex + 1)"
asp-route-Name="#ViewData["Name"]"
asp-route-Phone="#ViewData["Phone"]"
asp-route-Calls="#ViewData["Calls"]"
asp-route-Date="#ViewData["Date"]"
Next
</a>
why not use a single box to search everything or four search boxes using the method below in the tutorial?
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}

unable to call one button from without button

I have two buttons which are encapsulated with forms at SpringMVC/Thymeleaf.The interesting thing is I am not if I remove upper button, when I click second button nothing happens. I meant I am not able to call the PostMaping inside Controller which can be called if first button there. It could be an interesting issue for you but I tested it many times and could not find a reason why that happens.Could you please look at the code and let me know how it happens?
First Button:(encapsulated with form)
<form class="needs-validation" action="/showlimit" th:action="#{/showlimit}" th:object="${internetCustomer}" method="post">
<button type="submit"
class="list-group-item list-group-item-action list-group-item-primary">
<th:block th:text="#{label.customerdetails.button.limits}">
First Button
</th:block>
</button>
Second Button:(Encapsulated with form to call PostMapping at Controller)
<form class="needs-validation" action="/showlimit/{customerId}(customerId='123')}" th:action="#{/showlimit}" th:object="${limitModel}" method="post">
<button type="submit"
class="list-group-item list-group-item-action list-group-item- primary">
<th:block th:text="#{label.customerdetails.button.limits}">
Second Button
</th:block>
</button>
When you submit your second form, you are making a POST request to the url /showlimit/123. Since you are passing a parameter in an URL to show something, this should be a GET mapping, not a POST one. This affects how your request is processed by the controller, since POST request parameters are expected in the body, not the URL.
To pass this parameter to the controller, use the following mapping and method:
#GetMapping(/showlimit/{customerId})
public String foo(#PathVariable String customerId, Model model){
...
}
And change the method in your form to GET.

Bootstrap Dropdown with MVC - Keep last selected value displayed

I have the following Bootstrap dropdown in my Coverage MVC View. It defaults to "Active" status. When another status is selected, the associated items are shown on the page, for instance, "Past Coverage".
<div class="dropdown">
<button id="statusButton" class="btn dropdown-toggle ddlDisplay" type="button" data-toggle="dropdown">
Active
<span class="caret"></span>
</button>
<ul id="statusDropdown" class="dropdown-menu">
<li>Active</li>
<li>Past Coverage</li>
<li>Researching Now</li>
</ul>
</div>
I have the following javascript to change the html of the dropdown, so in this case it would say "Past Coverage".
$(".dropdown-menu li a").click(function () {
var selText = $(this).text();
$("#statusButton").html(selText + '<span class="caret"></span>');
This works fine, but you can only see, in this case, "Past Coverage", for a second, because then the href link is fired, the MVC Url.Action is called, the page reloads and Active is once again shown in the dropdown. How do I keep the most recent selected status in the dropdown?
You can use localStorage for storing. If you want to store in a per page session basis, then you can use sessionStorage.
Something like this should do.. Don't forget to clear the localStorage by calling localStorage.clear(); when needed.
$(".dropdown-menu li a").click(function () {
var selText = $(this).text();
$("#statusButton").html(selText + '<span class="caret"></span>');
localStorage['selText'] = selText; // store in storage
|);
$(document).ready(function() {
var selText = localStorage['selText'] || 'defaultValue';
if(selText != 'defaultValue') {
$("#statusButton").html(selText + '<span class="caret"></span>'); // Load previously selected item
}
});
I haven't really done something like this in particular so there must be a better way other than this. But this should work.

IE Form Submit Empty yet works with type=checkbox

I've looked at dozens of similar questions already but most solutions implement hidden inputs or extensive javascript and none have answered why one type of input works and the other doesn't.
This problem is specific to Internet Explorer, works on both Chrome and FF.
Here's my code to create the form:
#foreach (hello.Data.Models.Button btn in Model.Content.Buttons.OrderBy(b => b.Action))
{
if (btn.Action == "Close Message" && (Model.SurveyAuditExists == true || Model.SurveyContent == null))
{
<li class="response-button-item">
<input type="submit" class="response-button" name="#btn.Text" id="#btn.Text" onclick="submitForm.submit();" value="#hello.Biz.Helpers.ExtensionMethods.TrimString(btn.Text, new char[] { '&' })" />
</li>
}
And here's an example of the resulting HTML:
<form id="submitForm" action="/Go/Here/39354" method="post">
<ul id="response-button-list">
<li class="response-button-item">
<input name="&Agree" class="response-button" id="&Agree" onclick="submitForm.submit();" type="submit" value="Agree">
</li>
<li class="response-button-item">
<input name="&Disagree" class="response-button" id="&Disagree" onclick="submitForm.submit();" type="submit" value="Disagree">
</li>
</ul>
So when I click either Agree or Disagree on Chrome/FF it returns whether the user has Agreed or Disagreed but in IE it returns blank and results in an error as FormCollection and AllKeys are empty in my controller.
Changing the input type to checkbox and clicking on the box works and submits correctly in IE.
I haven't got nested forms in the page.
Any help would be appreciated!
From #stephenmuecke 's comment I tested the buttons without the JavaScript
onclick="submitForm.submit();"
As obviously this was competing with the input type="submit", removing the onclick attribute solved any issues.
So in the end the error was all my fault, hopefully this info helps someone else notice this quicker than I did.

How to read checkbox/radio value in freemarker?

I'm working with share forms in alfresco and trying to read the values of ticked checkboxes and checked radio buttons form a form. I extended both the user creation and userprofile form with these input controls and so far I have been unsuccessful at reading the textual values of said controls. Below is a snippet of code:
<div class="row">
<span class="label"><input id="${el}-input-spokenEnglish" type="checkbox" name="spokenLanguages" value="${msg("label.anglais"!"")?html}" /> ${msg("label.anglais")}</span>
<span class="label"><input id="${el}-input-spokenSpanish" type="checkbox" name="spokenLanguages" value="${msg("label.espagnol"!"")?html}" /> ${msg("label.espagnol")}</span>
<span class="label"><input id="${el}-input-spokenGerman" type="checkbox" name="spokenLanguages" value="${msg("label.allemand"!"")?html}" /> ${msg("label.allemand")}</span>
<span class="label"><input id="${el}-input-spokenChinese" type="checkbox" name="spokenLanguages" value="${msg("label.chinois"!"")?html}" /> ${msg("label.chinois")}</span>
<br/>
<span class="label">${msg("label.otherLanguages")} : </span>
<span class="input"><input id="${el}-input-spokenLanguages" type="text" size="30" maxlength="256" value="" <#immutablefield field="spokenLanugages" /> /> </span>
</div>
unfortunately I get nothing so far from whatever is returned and would gladly appreciate some insight into this.fre
If you look at userprofile.get.html.ftl, you'll see the following snippet:
<script type="text/javascript">//<![CDATA[
var userProfile = new Alfresco.UserProfile("${args.htmlid}").setOptions(
{
This means it's triggering a client-side JS file from Alfresco, in this case profile.js (see the head file). So just adding some input fields isn't enough.
You need to extend the client-side JS file.
In the function onEditProfile it gets the Dom elements.
But that's just for showing the actual fiels 'after' it's saved.
In profile.js you'll see: form.setSubmitAsJSON(true); that you have a json object from which you can get your fields.
And in userprofile.post.json.ftl it does a loop on the user.properties:
for (var i=0; i<names.length(); i++)
{
var field = names.get(i);
// look and set simple text input values
var index = field.indexOf("-input-");
if (index != -1)
{
user.properties[field.substring(index + 7)] = json.get(field);
}
// apply person description content field
else if (field.indexOf("-text-biography") != -1)
{
user.properties["persondescription"] = json.get(field);
}
}
user.save();
This probably means that you haven't extended the contentmodel of the cm:person object with your new properties.

Resources