I get this error: Could not find 'ShowToastr' ('ShowToastr' was undefined).
I am creating a Blazor app with .NET6.
This is the page:
#page "/hotel/rooms"
#inject ILocalStorageService localStorage
#inject IJSRuntime jsRuntime
#inject IHotelRoomService hotelRoomService
<h3>HotelRooms</h3>
#code {
private HomeViewModel HomeModel { get; set; } = new HomeViewModel();
public IEnumerable<HotelRoomDto> Rooms { get; set; } = new List<HotelRoomDto>();
protected override async Task OnInitializedAsync()
{
try
{
if (await localStorage.GetItemAsync<HomeViewModel>(SD.Local_InitialBooking) != null)
{
HomeModel = await localStorage.GetItemAsync<HomeViewModel>(SD.Local_InitialBooking);
}
else
{
HomeModel.NumberOfNights = 1;
}
await LoadRooms();
}
catch (Exception ex)
{
await jsRuntime.ToastrError(ex.Message);
}
}
common.js :
window.ShowToastr = (type, message) => {
if (type === "success") {
toastr.success(message, "Operation Successful")
}
if (type === "error") {
toastr.error(message, "Operation Failed")
}
}
I have two references on ToastrError :
public static class IJSRuntimeExtension
{
public static async ValueTask ToastrSuccess(this IJSRuntime JSRuntime, string message)
{
await JSRuntime.InvokeVoidAsync("ShowToastr", "success", message);
}
public static async ValueTask ToastrError(this IJSRuntime JSRuntime, string message)
{
await JSRuntime.InvokeVoidAsync("ShowToastr", "error", message);
}
}
While debugging HotelRooms.razor the whole try block passes, the LoadRooms(the method is entered) and after that the debugger enters the catch block where I get this error.
This is the index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>HiddenVilla_Client</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="HiddenVilla_Client.styles.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet" />
</head>
<body>
<div id="app">
<div style="position:fixed;top:50%;left:50%;margin-top:-50px;margin-left:-100px;">
<img src="images/ajax-loader.gif" />
</div>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
Reload
<a class="dismiss">🗙</a>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js" integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw==" crossorigin="anonymous"></script>
<script src="https://js.stripe.com/v3/" defer></script>
<script src="js/common.js"></script>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
Please move ShowToastr to OnAfterRender event, this is the event when UI is fully ready and accessible.
In index.html "you already have it"
link the toastr cdns
In your common.js
function toastrSuccess(message){
toastr.success(message);
}
function toastrError(message){
toastr.error(message);
}
your component
#page "/hotel/rooms"
#inject ILocalStorageService localStorage
#inject IJSRuntime jsRuntime
#inject IHotelRoomService hotelRoomService
<h3>HotelRooms</h3>
#code {
private HomeViewModel HomeModel { get; set; } = new HomeViewModel();
public IEnumerable<HotelRoomDto> Rooms { get; set; } = new List<HotelRoomDto>();
protected override async Task OnInitializedAsync()
{
try
{
if (await localStorage.GetItemAsync<HomeViewModel>(SD.Local_InitialBooking) != null)
{
HomeModel = await localStorage.GetItemAsync<HomeViewModel>(SD.Local_InitialBooking);
}
else
{
HomeModel.NumberOfNights = 1;
}
await LoadRooms();
//example of using toastr success
await jsRuntime.InvokeVoidAsync("toastrSuccess","what ever you want in success toastr");
}
catch (Exception ex)
{
await jsRuntime.InvokeVoidAsync("toastrError",ex.Message);
}
}
References
Related
I am using Rotativa to generate a PDF of a view with the intention of printing it.
I have the following code
public ActionResult PrintTicket(string tempTickID)
{
//var tick = ctx.vw_printTicket.Where(e => e.noTicket == tempTickID).FirstOrDefault();
// return View(tick);
var report = new ActionAsPdf("PrepareTicket", new { tempTickID = tempTickID });
return report;
}
ActionAsPdf allows me to open the "PrepareTicket" view as a pdf and then I can print.
Problem
The problem for me is this, The pdf takes over my entire page and while I can print I don't have access to my program's menus anymore cause it's now a PDF view.
Questions
Is it possible that I call the print dialog automatically instead of showing the pdf?
I think will work for my situation.
Regards
Hi I have tried to create a sample which will solve your issue.
Model
public class Ticketinfo
{
public string name { get; set; }
public int quantity { get; set; }
}
Created a Controller which has 3 Action Method
public class GenerateController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult PrintTicket(string tempTickID)
{
return new ActionAsPdf("RotativaPartialViewAsPdf", new { tempTickID = tempTickID });
}
public ActionResult RotativaPartialViewAsPdf(string tempTickID)
{
Ticketinfo Ticketinfo = new Ticketinfo()
{
name = "Demo",
quantity = 5
};
return PartialView("_RotativaPartialViewAsPdfl", Ticketinfo);
}
}
Partial View
#model WebApplication6.Models.Ticketinfo
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/bootstrap.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<table class="table">
<tr class="info">
<td>Lot</td>
<td>Name</td>
<td>Quantity</td>
</tr>
<tr class="success">
<td>#Model.name</td>
<td>#Model.quantity</td>
</tr>
</table>
</div>
</body>
</html>
Index View
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
<iframe src="#Url.Action("PrintTicket", "Generate", new {tempTickID = "1"})"
width="800px" height="600px">
</iframe>
</div>
</body>
</html>
Output
i am new in mvc. so could not figure out what to add in code to show entered order no and selected product name and id.
here is full code and dotnetfiddle url https://dotnetfiddle.net/6vn2GO
Model code
using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using System.Collections.Generic;
namespace HelloWorldMvcApp
{
public class OrderViewModel
{
[Display(Name = "Order number")]
public int? OrderNumber { set; get; }
[Display(Name = "Product")]
[Required(ErrorMessage = "Please select a product")]
public int SelectedProductId { set; get;}
public SelectList ProductList { get; set; }
}
public class Product
{
public int ID { set; get; }
public string Name { set; get; }
}
public static class Repository
{
public static IEnumerable<Product> FetchProducts()
{
return new List<Product>()
{
new Product(){ ID = 1, Name = "Ketchup" },
new Product(){ ID = 2, Name = "Mustard" },
new Product(){ ID = 3, Name = "Relish" }
};
}
}
}
Controller code
using System;
using System.Web.Mvc;
using System.Collections.Generic;
namespace HelloWorldMvcApp
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
OrderViewModel model = new OrderViewModel();
model.OrderNumber=null;
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult Index(OrderViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// save and redirect
// but for testing purposes
ConfigureViewModel(model);
return View(model);
}
private void ConfigureViewModel(OrderViewModel model)
{
IEnumerable<Product> products = Repository.FetchProducts();
model.ProductList = new SelectList(products, "ID", "Name");
}
}
}
View.cshtml code
#model HelloWorldMvcApp.OrderViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<!-- template from http://getbootstrap.com/getting-started -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<!-- CSS Includes -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style type="text/css">
.field-validation-error {
color: #ff0000;
}
</style>
</head>
<body>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<h1>Hello Stranger</h1>
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(m => m.OrderNumber)
#Html.TextBoxFor(m => m.OrderNumber, new {#class="form-control"})
#Html.ValidationMessageFor(m => m.OrderNumber)
</div>
<div class="form-group">
#Html.LabelFor(m => m.SelectedProductId)
#Html.DropDownListFor(m => m.SelectedProductId, Model.ProductList, "-Please select-", new {#class="form-control"})
#Html.ValidationMessageFor(m => m.SelectedProductId)
</div>
<button type="submit" class="btn btn-success submit">Save</button>
}
</div>
</div>
<!-- JS includes -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
</script>
</body>
</html>
please tell me what code i need to add in view html to show entered order no and selected product name and id. thanks
You could set the value of your order number on the [HttpPost] Action method and check if it's null on the view side and show/hide stuff accordingly.
Another (probably better) alternative would be to just create a new view and return that when the model state is valid. To get the order number, you'll need to fetch the inserted ID from the database and pass that to the view.
Edit to show some code:
Controller Code:
using System;
using System.Web.Mvc;
using System.Collections.Generic;
namespace HelloWorldMvcApp
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
OrderViewModel model = new OrderViewModel();
model.OrderNumber=null;
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult Index(OrderViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// save and redirect
// but for testing purposes
ConfigureViewModel(model);
// you'll need to figure out how you're generating your
// order numbers
//
model.OrderNumber = 1; // just set this statically for now for POC
return View(model);
}
private void ConfigureViewModel(OrderViewModel model)
{
IEnumerable<Product> products = Repository.FetchProducts();
model.ProductList = new SelectList(products, "ID", "Name");
}
}
}
View Code:
#model HelloWorldMvcApp.OrderViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<!-- template from http://getbootstrap.com/getting-started -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<!-- CSS Includes -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style type="text/css">
.field-validation-error {
color: #ff0000;
}
</style>
</head>
<body>
<div class="container">
#{
if(Model.OrderNumber == null)
{
<div class="col-md-6 col-md-offset-3">
<h1>Hello Stranger</h1>
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(m => m.OrderNumber)
#Html.TextBoxFor(m => m.OrderNumber, new {#class="form-control"})
#Html.ValidationMessageFor(m => m.OrderNumber)
</div>
<div class="form-group">
#Html.LabelFor(m => m.SelectedProductId)
#Html.DropDownListFor(m => m.SelectedProductId, Model.ProductList, "-Please select-", new {#class="form-control"})
#Html.ValidationMessageFor(m => m.SelectedProductId)
</div>
<button type="submit" class="btn btn-success submit">Save</button>
}
</div>
} else {
<div>show your confirmation stuff here</div>
}
}
</div>
<!-- JS includes -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
</script>
</body>
</html>
that will reuse the same view, though as I said, I'd recommend using a different view.
I have a working action which is using the ExecAndWait Interceptor. My wait page is
<%# page language="java" pageEncoding="UTF-8" session="false"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="2"/>"/>
</head>
<body>
<h3>Waiting</h3>
<div id="wait-result">
</div>
</body>
</html>
this is working correctly and adding a breakpoint to my action I can see that the action only gets invoked once regardless of the number of refreshes. As it should.
Now, if I remove the meta-refresh tag and replace it with a JQuery script to
reload the page, what I see is my action gets invoked for each request and the final result page never arrives.
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js" ></script>
<script>
var repeat = false;
function executeQuery() {
$.ajax({
type: 'GET',
url: 'search',
async: false,
success: function(data) {
if ($(data).find('#wait-result')) {
repeat = true;
} else {
repeat = false;
$('#wait-result').html(data);
}
}
});
if (repeat) {
setTimeout(executeQuery, 1000);
}
}
$(document).ready(function() {
setTimeout(executeQuery, 1000);
});
</script>
</head>
<body>
<h3>Waiting</h3>
<div id="wait-result">
</div>
</body>
</html>
Is it possible to use the ExecAndWait Interceptor with a JQuery Ajax call? If so, what am I doing wrong?
Regards
EDIT
As requested here is the action
package com.harkonnen.actions.search;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.struts2.convention.annotation.InterceptorRefs;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.harkonnen.services.filter.ZeroResFilter;
import com.harkonnen.services.search.SearchService;
import com.harkonnen.services.search.Town;
#Component
#Scope("protototype")
#Namespace("/search")
#ParentPackage("search")
#InterceptorRefs({
#InterceptorRef(value="secureStack"),
#InterceptorRef(value="execAndWait", params={"delay", "500", "delaySleepInterval","500"}
)
})
#Results({
#Result(name="input", location="start.jsp"),
#Result(name="success", type="redirectAction", location="start" ),
#Result(name="wait", location="wait.jsp")
})
public class Search extends BaseAction {
private int x;
private int y;
private int radius;
private List<Town> towns;
#Autowired
SearchService service;
private static final Logger logger = Logger
.getLogger(Search.class.getName());
public String execute() {
try {
towns = new ZeroResFilter(service.search(x,y,radius)).filter();
System.out.println("Search Complete");
} catch (SQLException e) {
logger.error(e);
addActionError("Sorry, there was an unexpected error with your query.");
return INPUT;
}
if (towns.size() == 0) {
addActionError("There were no results found for the specified search.");
return INPUT;
}
context.setSearchX(x);
context.setSearchY(y);
context.setRadius(radius);
context.setResults(new ArrayList<Town>(towns));
context.setTowns(towns);
return SUCCESS;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
}
The base action
package com.harkonnen.actions.search;
import java.util.Map;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.interceptor.SessionAware;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.harkonnen.services.SearchContext;
import com.opensymphony.xwork2.ActionSupport;
#Component
#Scope("protototype")
#Namespace("/search")
public class BaseAction extends ActionSupport implements SessionAware {
protected SearchContext context;
protected boolean isLoggedIn() {
return true;
}
#Override
public void setSession(Map<String, Object> session) {
this.context = (SearchContext) session.get("context");
}
public SearchContext getContext() {
return context;
}
}
The success jsp
<%# page language="java" pageEncoding="UTF-8" session="false"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">#import "<%=request.getContextPath()%>/resources/css/global.css";</style>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
<title>HoTH Search</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js" ></script>
</head>
<body id="body">
<div id="container">
<div id="login">
<s:action var="login" name="login" executeResult="true"/>
</div>
<div id="perform">
<s:action var="search" name="action-prompt" executeResult="true"/>
<s:actionerror/>
</div>
<div id="results">
<s:action var="results" name="display-search-results" executeResult="true"/>
</div>
<div id="footer-wrapper">
<p>Copyright ©2015 Harkonnen Solutions.</p>
</div>
</div>
</body>
</html>
Ok, found it.
The problem was trying to parse the response to the GET request into an HTML object and then trying to run a selector.
Changing the line
if ($(data).find('#wait-result')) {
to
if (data.indexOf('#wait-result') >=0) {
fixes the problem and now everything runs as expected
I'm new to MVC. I want to be able to change a button/divs/textboxes text when a view's button is clicked. I found a tutorial online that showed me the following but when I click the button I'm getting redirected to another page. That page shows the text instead. I haven't touched the default Global.aspx
View
#using (Ajax.BeginForm("ExamineTextBox", new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.TextBox("textBox1")
<input type="submit" value="Button" />
<span id="result" />
}
Controller
public string ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return "This text is MVC different from before!";
}
return String.Empty;
}
Make sure you have included the jquery.unobtrusive-ajax.js script to your page.
If you are using the default bundles (take a look at ~/App_Start/BundleConfig.cs - you will see a jqueryval bundle defined which combines and minifies all ~/Scripts/jquery.unobtrusive* and "~/Scripts/jquery.validate*" files):
#Scripts.Render("~/bundles/jqueryval")
and if not using bundles you could include only this script individually:
<script type="text/javascript" src="~/scripts/jquery.unobtrusive-ajax.js"></script>
It is this script that is required for Ajax.* helpers to work. As it name indicates it unobtrusively AJAXifies them. It depends on jQuery so make sure you have that one included as well.
Side note: In ASP.NET controller actions should return ActionResults, not strings:
public ActionResult ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return Content("This text is MVC different from before!");
}
return Content(String.Empty);
}
Here's how your full view code might look:
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
</head>
<body>
#using (Ajax.BeginForm("ExamineTextBox", new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.TextBox("textBox1", "Initial Data")
<input type="submit" value="Button" />
<span id="result" />
}
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
</body>
</html>
and the controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return Content("This text is MVC different from before!");
}
return Content(String.Empty);
}
}
I want to validate form when click client button out of form, i tryed some method but all failed,help please?
source code:
#model MvcTest.Models.Movie
#{
ViewBag.Title = "Home Page";
Html.EnableClientValidation(true);
}
<script src="../../Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
#using (Html.BeginForm("TestValidate", "Home", FormMethod.Post, new { id = "tf" }))
{
#Html.LabelFor(m => m.Title)
#Html.EditorFor(m => m.Title)
#Html.ValidationMessageFor(m => m.Title)
}
<a onclick="test(event)" href="#">
<script type="text/javascript">
function test() {
//How to write here?
}
</script>
namespace MvcTest.Models
{
public class Movie
{
public int ID { get; set; }
[Required(ErrorMessage = "Error Message Test,I want you")]
public string Title { get; set; }
}
public class MovieDBContext : DbContext {
public DbSet<Movie> Movies { get; set; }
}
}
I invoked valid but ,it always warning the object form don't support this methord "validate()"
$(document).ready(function () {
$("#myform").validate();
$("test").click(function() {
alert("Valid: " + $("#myform").valid());
return false;
});
});
I have import js like this:
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/lib/jquery.delegate.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/jquery.validate.js"></script>
or these:
<script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
You're looking for the valid method.