I have the following code on my cshtml page:
<div class="large reveal" id="draftProductModal" data-reveal>
<button class="close-button" data-close aria-label="Close modal" type="button">
<span aria-hidden="true"><i class="fa fa-times-circle-o"></i></span>
</button>
</div>
<div class="input-group">
<input type="text" class="input-group-field" id="draftSearchProducts" name="draftSearchProducts" placeholder="SearchProducts" />
<div class="input-group-button">
<!--Add product to order lines button-->
<a id="draftAddProduct" class="hollow button secondary" data-open="draftProductModal"><i class="fa fa-plus"></i> Search Products</a>
</div>
</div>
I need to take the value in the draftSearchProducts text field, pass it to a controller that returns a partialview:
public ActionResult SearchResults(string keywords, int queryLimit = 20, int offset = 0)
{
try
{
//connect to db, grab data return results
searchResults.ProductDetails = products.ToList();
return PartialView("_SearchResults", searchResults);
}
catch (Exception ex)
{
throw ex;
}
}
I need to send in the keyword to the controller, return the partial view and load it into the draftProductModal div and display the div. How is this done? I am new to front end development.
Tried this code:
var url = '/ProductsController/SearchResults';
$('#draftAddProduct').click(function () {
var keyWord = $('draftSearchProducts').val();
$('#draftProductModal').load(url, { keywords: keyWord });
});
And all I get is a 404 error, so it appears I am not hitting my controller. I think I am getting close, I just need to find out how to access the controller ActionResult. Still accepting help.
Related
I have applied the asp.net authorization in my views but it seems not to apply. I am using resource. author to display buttons on list.
public class IncidentAuthorizationHandler: AuthorizationHandler<SameAuthorRequirement, Incident>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
SameAuthorRequirement requirement,
Incident resource)
{
if (context.User.Identity?.Name == resource.CreatedBy)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
this is the code in my view but it seems not to work
<td>
<div class="btn-group" role="group">
<button id="btnGroupDrop1" type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Select an Action
</button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
#if ((await AuthorizationService.AuthorizeAsync(User, "EditPolicy")).Succeeded)
{
<a class="dropdown-item-custom" asp-action="EditIncident" asp-controller="Incident" asp-route-Id="#i.IncidentId"><i class="fa fa-sm fa-edit text-white mr-3"></i>Edit</a>
}
<a class="dropdown-item-custom" asp-action="ViewIncident" asp-controller="Incident" asp-route-Id="#i.IncidentId"><i class="fa fa-sm fa-comment text-white mr-3"></i>View</a>
<a class="dropdown-item-custom" asp-action="PrintIncident" asp-controller="Incident" asp-route-Id="#i.IncidentId"><i class="fa fa-sm fa-print text-white mr-3"></i>Print</a>
<a class="dropdown-item-custom" asp-action="DeleteIncident" asp-controller="Incident" asp-route-Id="#i.IncidentId"><i class="fa fa-sm fa-trash text-white mr-3"></i>Delete</a>
</div>
</div>
</td>
the user is the owner of the document but the button is not showing. it seems it does not recognize the owner. any assistance is appreciated
the startup looks like this
services.AddAuthorization(options =>
{
options.AddPolicy("EditPolicy", policy => policy.Requirements.Add(new SameAuthorRequirement()));
});
Your issue can be solved by adding this code in your program.cs file:
builer.Services.AddSingleton<IAuthorizationHandler, IncidentAuthorizationHandler>();
For testing purpose, I followed the MS Document created a project, here is my own Handler code:
public class MinimunAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
{
var userEmailClaim = context.User.FindFirst(c => c.Type == ClaimTypes.Email);
var userEmail = Convert.ToString(userEmailClaim.Value);
if (userEmail == "123#gmail.com")
{
context.Succeed(requirement);
}
else
{
return Task.CompletedTask;
}
return Task.CompletedTask;
}
}
And here is the code I added to my program.cs file:
builder.Services.AddSingleton<IAuthorizationHandler, MinimunAgeHandler>();
builder.Services.AddAuthorization(options =>{
options.AddPolicy("AtLeast21", policy => policy.Requirements.Add(new MinimumAgeRequirement("123#gmail.com")));});
Ignore the Handler's name, I followed the document and just changed the inside function. Now here is my index page's code:
#using Microsoft.AspNetCore.Authorization
#inject IAuthorizationService AuthorizationService
#{ViewData["Title"] = "Home Page";}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about building Web apps with ASP.NET Core.</p>
</div>
#if ((await AuthorizationService.AuthorizeAsync(User, "AtLeast21")).Succeeded)
{
<p>This paragraph is displayed because you fulfilled PolicyName.</p>
}
At last, here is my test result:
You can see from the picture, when login as "123#gmail.com", the paragraph will be shown.
I have a controller from where I have to show notification to the user on three different scenarios.
successful insertion of data
successful update of data
in case of error
For these different scenarios, I want to display three different types of notification style boxes. Please see the attached image.
These three boxes have different CSS styles for icons and box styling.
This is what I've written so far in my controller class
[HttpPost]
public ActionResult AddorEdit([Bind(Include = "Id,PatternName")] Pattern pattern)
{
try
{
if (pattern.Id <= 0)
{
// for INSERT OPERATION
TempData["UserMessage"] = new { CssClassName = "alert alert-success alert-dismissible", Title = "Success!", Message = "Operation Done." };
return RedirectToAction("Success");
}
else
{
// for UPDATE OPERATION
TempData["UserMessage"] = new { CssClassName = "alert alert-info alert-dismissible", Title = "Success!", Message = "Successful Update" };
return RedirectToAction("Success");
}
}
catch (Exception)
{
TempData["UserMessage"] = new { CssClassName = "alert alert-danger alert-dismissible", Title = "Success!", Message = "Error." };
return RedirectToAction("Success");
}
}
Is it possible to use single TempData for displaying these three different boxes or I have to make three different TempData for these three different cases.
When I am trying to use the above TempData variable, getting red underline in CssClassName, Title and Message.
// view page
#if (TempData["UserMessage"] != null)
{
<div class="alert #TempData["UserMessage"].CssClassName">
<strong>#TempData["UserMessage"].Title</strong> #TempData["UserMessage"].Message
</div>
}
Css for the notification boxes
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5><i class="icon fas fa-ban"></i> Alert!</h5>
Danger ...
</div>
<div class="alert alert-info alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5><i class="icon fas fa-info"></i> Alert!</h5>
Info alert preview. This alert is dismissable.
</div>
<div class="alert alert-warning alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5><i class="icon fas fa-exclamation-triangle"></i> Alert!</h5>
Warning alert preview. This alert is dismissable.
</div>
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5><i class="icon fas fa-check"></i> Alert!</h5>
Success alert preview. This alert is dismissable.
</div>
Also, I came to this website while doing research on this matter but don't know whether it is suitable in my case or not.
https://exceptionnotfound.net/mvc-in-practice-tempdata/
The way I see it you have basically two options:
Making a class/struct containing the data required, fill it and add it to your viewbag/tempdata. Then on your viewpage you could cast the object to your class.
Convert your anonymous object to a JSON string, then convert it back in your viewpage
The second option is probably the easiest way of doing it. Simply add using System.Web.Helpers to your controller and set your TempData like this:
TempData["UserMessage"] = Json.Encode(new { CssClassName = "alert alert-success alert-dismissible", Title = "Success!", Message = "Operation Done." });
On your viewpage you can then use the following:
#if (TempData["UserMessage"] != null)
{
dynamic userMessage = Json.Decode(TempData["UserMessage"]);
<div class="#userMessage.CssClassName">
<strong>#userMessage.Title</strong> #userMessage.Message
</div>
}
For the sake of completeness, here is how you would do the first option:
Create a struct/class:
public struct AlertMessage
{
public string CssClassName;
public string Title;
public string Message;
}
Then in your controller set your TempData like this:
TempData["UserMessage"] = new AlertMessage() { CssClassName = "alert alert-success alert-dismissible", Title = "Success!", Message = "Operation Done." };
Then in your viewpage you can cast your TempData object back to your AlertMessage like this:
#if (TempData["UserMessage"] != null)
{
AlertMessage userMessage = (TempData["UserMessage"] as AlertMessage);
<div class="#userMessage.CssClassName">
<strong>#userMessage.Title</strong> #userMessage.Message
</div>
}
Please note that if you do this you have to add a #using at the top of your viewpage with the namespace of your struct/class.
I’d like to use a Button/link/whatever to call a xQuery function from my eXist Webapp and use the returned value to display a Bootstrap alert. So include a
<button type="button" class="btn btn-danger btn-circle">execute xQuery</button>
inside my html and if it’s clicked evaluate
let $name := "Peter"
return <div class="alert alert-success" role="alert">Hi {$name}</div>
(actually I want something more complex than this, but you get the idea..)
and return
<div class="alert alert-success" role="alert">Hi Peter</div>
inside my Page. Is this possible and if, how?
Using the Templating System does not help me here and just linking to an xQuery in my Database executes the query but redirects to another page showing the result. Can I use AJAX to evaluate the xQuery and modify the current DOM?
Thanks!
For reasons of completeness and future reference I will post a MWE of this here:
Add a Button and a result panel to a page in eXist:
<a class="btn btn-danger run" id="path/to/the/xquery/in_your_app.xq" href="#">
<i class="glyphicon glyphicon-play" /> Run xQuery
</a>
<img class="load-indicator" src="resources/img/ajax-loader.gif" />
<div style="margin-top: 12pt;" class="output" />
Have a runxquery.js in your apps’ resources folder and reference it in your page.html:
$(document).ready(function() {
$(".run").click(function(ev) {
ev.preventDefault();
file = this.id;
var output = $(this).parent().parent().find(".output");
var indicator = $(this).parent().parent().find(".load-indicator");
function run() {
indicator.show();
output.hide();
$.ajax({
url: "/exist/rest/db/apps/yourapp/" + file,
type: "GET",
success: function(result) {
indicator.hide();
output.html(result);
output.slideDown(600);
}
});
}
if (output.is(":empty")) {
run();
} else {
output.slideUp(800, function() {
output.empty();
run();
});
}
});
});
Clicking the Button will trigger the xquery defined in the id of the button inside your apps folder.
If running the xQuery should return HTML Code, you need to specify this in the xQuery:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "html";
declare option output:media-type "application/html";
let $text := "This is the alert text"
return
<div class="alert alert-success alert-dismissible" data-dismiss="alert" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"/>
{$text}
</div>
I'm new to aurelia. I'm looking to find the best method for adding classes on click events.
I simply want to click approve or request information, and then add a class to the corresponding "contact card". This class would change the background color.
I know it's probably simple, but I thought I'd look here for the best method.
Here's an image to what I've got:
Apologies for the wait, work has been a bit busy.
This is my first time posting on S.O., so I apologize for any expectations I'm not meeting.
<div class="col-sm-4">
<button class="btn btn-success col-sm-12" click.delegate="goodBoi()">
approve contact
</button>
</div>
<div class="col-sm-4">
<button class="btn btn col-sm-12" click.delegate="requestContact()">
request information
</button>
</div>
</div>
the element to be changed is named "list-group-item", containing the
contact's details(code shown above).
<template>
<div class="contact-list">
<ul class="list-group">
<li repeat.for="contact of contacts" class="list-group-item ${contact.id === $parent.selectedId ? 'active' : ''}">
<a route-href="route: contacts; params.bind: {id:contact.id}" click.delegate="$parent.select(contact)">
<h4>${contact.firstName} ${contact.lastName}</h4>
<p>${contact.company}</p>
<p>${contact.email}</p>
<h6>${contact.approval}</h6>
</a>
<a route-href="route: contacts; params.bind: {id:contact.id}">
<p>${contact.phoneNumber}</p>
</a>
</li>
</ul>
</div>
goodBoi() {
let result = confirm("Are you sure you want to confirm this contact?");
if (result === true) {
var standingShell = document.getElementsByClassName("list-group-item");
//im hoping here I would add a class to the new variable//
this.contact.approval = 'approved';
this.save();
}
}
//confirms contact, changing color of approved contact//
//same thing here, just plan to give it a different color//
requestContact() {
let contactRequestText = "request sent to contact";
this.routeConfig.navModel.setTitle(this.contact.approval = contactRequestText);
this.ea.publish(new ContactUpdated(this.contact));
}
There are many ways to set a CSS-class using Aurelia. Following I prepared an example gist:
Template:
<template>
<h1>${message}</h1>
<div class="form-group ${clicked ? 'red' : 'blue'}" style="width: 100px; height: 100px;">
</div>
<div class="form-group">
<button click.delegate="save()">
Click me
</button>
</div>
</template>
And the code class:
#autoinject
export class App {
#bindable clicked = false;
save(){
this.clicked = true;
}
}
https://gist.run/?id=425993b04a977466fa685758389aa2b4
But there are other, cleaner ways:
using ref in a custom element.
custom attributes.
Include jQuery for using e.g. $('#myelement').addClass()
I'm trying to learn more about MVC 5 so I'm writing a bloging site for myself to learn more as I go.
I have set up a select list for tags and would like to be able to add new tags from the create blog entry page rather than having to remember to set the tags up before creating a new post. I'm thinking down the lines of a "Add Tag" button which displays a bootstrap modal window where the user can add a new tag.
Here is my controller action:
public ViewResult CreateBlogPost()
{
CreateEditBlogViewModel viewModel = new CreateEditBlogViewModel();
viewModel.BlogPost = new Core.BlogPost();
viewModel.BlogPost.ShortBody = "<p>Something short and sweet to describe the post</p>";
viewModel.BlogPost.Body = "<p>Enter something blog worthy here...</p>";
viewModel.Tags = new SelectList(_blogRepo.BlogTags(), "Id", "Name");
viewModel.Categories = new SelectList(_blogRepo.BlogCategories(), "Id", "Name");
return View(viewModel);
}
And here is the HTML in the view:
<div class="row">
<div class="form-group">
#Html.LabelFor(m => m.BlogPost.Tags, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.ListBoxFor(m => m.SelectedTags, Model.Tags, new { #class = "form-control chosen-select", #data_placeholder = "Start typing to see a list of tags" })
</div>
</div>
</div>
<div class="row">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#tagModal">
Add Tag
</button>
</div>
Here is my partial view for the modal window:
#using (Html.BeginForm("SaveTag", "Home", FormMethod.Post, new { id = "tag-form" }))
{
#Html.AntiForgeryToken()
<!-- Modal -->
<div class="modal fade" id="tagModal" tabindex="-1" role="dialog" aria-labelledby="tagModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="tagModalLabel">Enter a name for a new tag</h4>
</div>
<div class="modal-body">
<input type="text" id="Name" placeholder="Enter a new tag name" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
}
Is it possible to add a tag on the client side, persist it into the db and then add it to my tags select list without refreshing the page?
PS: FYI I'm using the Chosen multi-select from here.
#section scripts {
<script type="text/javascript" src="~/Scripts/chosen.jquery.min.js"></script>
<script type="text/javascript">
$(".chosen-select").chosen()
</script>
}
EDIT: I have updated the question with all the code that makes the view give the user the modal window to enter a new tag name. I'm just not sure how to post without navigating away from the page so I'm guessing some sort of Ajax post is required. And then what to do with the data that is returned from that post. How do I then add that new persisted record to the select list?
I know the tag isn't passing to the controller method as it's not bound to any sort of model but being as I'm using a view model on the parent view, I'm not sure how I would handle that here either.
In order to dynamically add a new BlogTag in the view you will need to post the new tag Name using ajax, to a controller method that saves the BlogTag and returns its new ID value. Your controller method would be something like
[HttpPost]
public JsonResult CreateTag(string name)
{
BlogTag tag = new BlogTag(){ Name = name };
db.BlogTags.Add(tag);
db.SaveChanges();
return Json(tag.ID);
// If the above code could result in an error/exception, catch it and return
// return Json(null);
}
Then in the view, handle the dialogs submit button to post the value and update the tag list
var url = '#Url.Action("CreateTag")';
var tagList = $('#SelectedTags');
$('#tag-form').submit(function() {
var tagName = $('#Name').val();
$.post(url, { name: tagName }, function(id) {
if (id) {
// add the new tag to the list box
tagList.append($('<option></option>').val(id).text($('#Name').val()));
// trigger the chosen update
tagList.trigger("chosen:updated");
} else {
// Oops - display an error message?
}
}).fail(function (result) {
// Oops - display an error message?
});
return false; // cancel the default submit
});
Side note: I would recommend that you create a view model for BlogTagVM (containing a property for the Name with validation attributes) and an associated partial view (say _AddBlogTag.cshtml) that generates the dialog html, so that in the main view you can use #Html.Partial("_AddBlogTag", new BlogTagVM()) which will allow you to use the strongly typed html helpers, and to include client side validation.
Note also that nested <form> elements are invalid html so ensure that html for the dialog is outside the main <form> tag for the view.
I am doing something similar, I think it might help. In my case, I'm "moving" values from one list to another (from "available" to "used") and then saving the values of the "used" list. Anyway, in the controller, the "used" list shows up as an array of strings. Here's my code:
public ActionResult PinchHit(FormCollection form, LineupViewModel lvm, String[] UsedPlayers)
{
[Snip]
if (ModelState.IsValid && lineupResults.IsValid)
{
[Snip]
foreach (String usedID in UsedPlayers)
{
gameState.HomeUsedPlayersIDs.Add(Convert.ToInt32(usedID));
}
uow.Repository<GameState>().Update(gameState);
uow.SaveChanges();
return RedirectToAction("Index", "GameSummary");
}
[Snip]
return View(lvm2);
}
Hope that helps.
Per my comment:
Here is an AJAX call-back mechanism I used to retrieve data from the database without reloading the page, you could use it to save data to the database instead.
<script type="text/javascript">
function getPositions(id, control) {
$.ajax({
url: "#Url.Action("GetPositions", "Lineup")",
data:
{
id: id
},
dataType: "json",
type: "POST",
error: function () {
alert("An error occurred.");
},
success: function (data) {
$(control).html("");
$.each(data, function (i, item) {
$(control).append("<option value=\"" + item.Value + "\">" + item.Text + "</option>");
}
);
}
});
}
</script>
then in the controller:
[HttpPost]
public ActionResult GetPositions(int id)
{
Player player = uow.Repository<Player>().GetById(id);
if (player == null)
{
return (null);
}
List<SelectListItem> positionList = new SelectList(player.Positions, "ID", "ShortName").ToList();
return Json(positionList);
}
Pretty standard stuff really.