ASP.NET MVC Razor get textbox value - c#

How can I get the value of a textbox using razor?
<div>
<input type="text" id="somevalue" name="somevalue" class="form-control"/>
<input type="button" value="Search" class="btn btn-success"/>
</div>
<ul id="ReportsList" class="nav">
#foreach (var item in Model){
var roomName= document.getElementByID('somevalue').value
if (item.roomName == roomName) {
<li class="errorItem">
<a href="#" class="list-group-item">
<i class="fa fa-warning fa-fw"></i> #Html.DisplayFor(modelItem => item.roomName)
<span class="pull-right text-muted small">#Html.DisplayFor(modelItem => item.roomCapacity) pers.
</span>
..........
}
Is it possible to get the value of the textbox using MVC Razor? Cause using the getElementByID doesn't seem to work in razor...

Don't be brought down by the down-ticks.
You are obviously new to Razor and Mvc & Javascript. You problem is that you are mixing a server-side language with a client-side language. Razor is a server-side language so you will not be able to access client-side code (ie html or javascript) using Razor. Razor is used to render html to the client browser. Think of the code that you see in a cshtml file as a template for the code that will become an html file. The javascript on the other hand will only run when it gets to the users browser.
Now, lets try to make some sense of your code.
<div>
<input type="text" id="somevalue" name="somevalue" />
<input type="button" value="Search" />
</div>
<ul id="ReportsList" class="nav">
#foreach (var item in Model)
{
var roomName= document.getElementByID('somevalue').value; // This is javascript code.
if (item.roomName == roomName) {
<li>
#Html.DisplayFor(modelItem => item.roomName)
#Html.DisplayFor(modelItem => item.roomCapacity)
</li>
}
}
</ul>
I removed the classes to make it more legible. The problem above is that you are trying to find a value to use with your razor code. That code is running before it gets to the browser so that won't work.
You cannot solve this problem using Razor. That means your DisplayFor's are going to be useless for your scenario.
You need javascript to solve the problem, so you will need to do away with the Razor Code. Assuming your Model has as list of object with the properties you created in your example, you could do something like this.
<script type="text/javascript">
var data = #(Html.Raw(Json.Encode(Model));
for(var o in data) {
var item = data[o];
// You need to create an element here and add it to the ul here
// You could use jquery.
}
</script>
Unfortunately, you have the wrong tools here.
To actually accomplish what you are trying to do you are going to be better off investing in some javascript frameworks. I suggest that you learn AngularJs to do this.
Concerning Organization of Javascript
As stated in the comments you can use a script tag in your cshtml file. Unfortunately, this is not your problem. I added a little bit of a way to organize your javascript as well.
your.cshtml file.
<script type="text/javascript">
.. getElementById in here and do something.
</script>
Better Organization Might Look Like This
Put the code in a javascript file. In this example the name is person.js. I am using a person example because it is an easy way to look at creating an usable object in javascript. In this case person is the object.
person.js
function Person() {
}
Person.prototype = {
// Sets the element with id = "nameId" to "Jim Bob"
setName: function() {
var element = document.getElementById("nameId");
// Now do something with it.
element.innerHTML = "Jim Bob"; // get some user input.
}
};
// You could initialize this as a global reference.
// I don't recommend this but it will be the easiest way for now.
var person = new Person();
Next, you would have to use it somehow. The simplest way to use it is not the best way.
<button id="setNameButton" onclick="person.setName()">Set Name</button>
Improved example using JQuery
This example will bind the event in an unobtrusive way (ie. you won't be mixing javascript and html).
function Person() {
this.initialize();
this.name = "Jim Bob";
}
Person.prototype = {
initialize: function() {
// get reference to this object.
var self = this;
// Set up the click for button.
$(document).on('click', "#setNameButton", function() {
// Set the name
self.setName();
});
}
// Sets the element to this.name field.
setName: function() {
var element = document.getElementById("nameId");
// Now do something with it.
element.innerHTML = this.name;
}
};

Related

How do I post to Razor Page with model - .netcore 3.0

I am trying to do a simple post to a .netcore 3.0 Razor page with some model data. I want to get the data while in the first page - then send that to a generic page to show the modal data on another page.
Normally I would do with in a Controller in MVC and return a View while passing in the model.
This is what I am doing (RedirectToPage) which is doing a GET (not POST). I want to post the data.
Index Page
<div class="text-center">
<h1 class="display-1">Test</h1>
<form method="post">
<button class="btn btn-dark" type="submit" asp-page-handler="Something">Get Lookup Table Data</button>
</form>
</div>
IndexModel
public IActionResult OnPostSomething()
{
var result = _service.GetTableData($"{id}").Result;
Objresult rr = new Objresult();
rr.Title = "Get Lookup Tables";
rr.Request = "";
rr.Json = result;
return RedirectToPage("Results","OnPost", rr);
}
https://localhost:44302/Results?Title=Test&Request=&Json=&handler=OnPost
I now realized the Razor Pages are no supposed to work this way. Lesson Learned.
The proper way for me to do what I want in this case would be to create a WebApi for the for my data and then call it in the Razor Pages.

Razor Pages: Set cookie from _Layout.cshtml

In _Layout.cshtml I have menu to change language of the application, like:
<nav id="nav-lang">
<ul>
<li>
EN
</li>
<li>
PL
</li>
</ul>
</nav>
What it does is reloading the page and sets new culture - works well. The thing is, that if the user changes culture and then go to other page within my app, default culture is loaded. I checked my options and the best choice seems to be setting a cookie "UserCulture" to e.g. "c=pl-PL|uic=pl-PL". The thing is I don't really know how to do it from in razor pages. I think that I should have a with asp-page-handler set to some method (e.g. "SetCulture") and have setting cookie in that method, but this causes some problems:
where to put "SetCulture" if the form would be in _Layout.cshtml?
_Layout.cshtml doesn't have code behind file
how to submit the form from anchor? If I put input type="submit" it
ruins the look of the menu completely.. I know I could do it from js
but I try to avoid js where it's not absolutely required, especially
for such basic stuff..
I might be missing something very basic here, I'm quite new to Razor Pages still. From the hindsight I should have probably sticked to MVC but Razor Pages was said to be easier..
Thanks, Brad. The solution you proposed works well. In the meantime I've got also other suggestion elsewhere and I'll post it too for anyone searching the answer in future.
In _Layout.cshtml:
<nav id="nav-lang">
<ul>
<li><a asp-page="/Index" asp-page-handler="SetCulture" asp-route-culture="en-EN">EN</a></li>
<li><a asp-page="/Index" asp-page-handler="SetCulture" asp-route-culture="pl-PL">PL</a></li>
</ul>
</nav>
In code-behind of Index (or any other page having code-behind):
public async Task<IActionResult> OnGetSetCultureAsync(string culture)
{
HttpContext.Response.Cookies.Append("Culture", "c=" + culture + "|uic=" + culture);
var returnUrl = Request.Headers["Referer"].ToString();
if (returnUrl.Contains("?culture="))
{
var url = returnUrl.Substring(0, returnUrl.IndexOf("?culture="));
return Redirect(url + "?culture=" + culture);
}
else
{
return Redirect(returnUrl + "?culture=" + culture);
}
}
And of course, for both solutions to work, there must be info in Startup.cs >> Configure:
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("pl-PL")
};
var lo = new RequestLocalizationOptions // Localization Options
{
DefaultRequestCulture = new RequestCulture("en-US"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
};
var cp = lo.RequestCultureProviders.OfType<CookieRequestCultureProvider>().First(); // Culture provider
cp.CookieName = "Culture";
I haven't tested this out but what about setting the cookie using JavaScript and then reloading the page. The server side razor page code should check the code instead of a query parameter.
Something like the following on the _Layout page. Modify the menu to call a JS function instead of a link with a query parameter. In the JS set the cookie and reload the page.
<nav id="nav-lang">
<ul>
<li class="nav-item" onClick="setCulture('en-EN')">EN</li>
<li class="nav-item" onClick="setCulture('pl-PL')">PL</li>
</ul>
</nav>
...
<script>
function setCulture(culture) {
document.cookie = "culture="+culture;
location.reload();
}
</script>

CKEditor html content lifecycle: asp net mvc case

My content will be edited number of times.So i need to store result html to database and load it again when it is neccessary.Here is my current start implementation:
#using (#Html.BeginForm("EditArticle", "Admin", new { id = ViewData["id"] }))
{
<div id="editor"> </div>
<input type="submit" value="save changes" onclick = "setValue()" />
<input type ="hidden" id="value" name="html" />
}
<script>
var editor, html = 'Model.Text';
function createEditor() {
if (editor)
return;
var config = { width:"900px"};
editor = CKEDITOR.appendTo('editor', config,html);
}
function setValue() {
$("#value").val(editor.getData());
}
createEditor();
</script>
But I get eror with initialization html variable.So, could anyone show how correct encode / decode html?
EDIT
Here is data controller receives:
html = <p>ARTICLE 3</p>\r\n
Values like this I store in database and try insert again.
First things first, to fix your code syntactically, it should probably read something like:
var editor, html = '#Html.Raw(Model.Text)';
However, why not instead of dealing with the markup in JavaScript and having to escape and unescape it, dump it directly where it should go i.e.
<textarea name="editor1">#Html.Raw(Model.Text)</textarea>
<script>
CKEDITOR.replace( 'editor1' );
</script>
And then transform that textarea into your ckEditor? As per their basic example here: http://docs.ckeditor.com/#!/guide/dev_framed
Secondly, aside from that I am not sure what errors you are receiving with your controller, so you will have to post further details for me to help you beyond the above.
I hope this helps.

ASP.NET MVC & JQuery Dynamic Form Content

I would like to dynamically add fields to an ASP.NET MVC form with JQuery.
Example:
<script language="javascript" type="text/javascript">
var widgets;
$(document).ready(function() {
widgets = 0;
AddWidget();
});
function AddWidget() {
$('#widgets').append("<li><input type='text' name='widget" + widgets + "'/></li>");
widgets++;
}
</script>
<ul id="widgets">
</ul>
This works, but I was going to manually iterate the form values in the controller:
[AcceptVerbs("Post")]
public ActionResult AddWidget(FormCollection form)
{
foreach (string s in form)
{
string t = form[s];
}
return RedirectToAction("ActionName");
}
But it occurred to me when I send the user back to the Get Action in the Controller I will have to set the FormData with the values entered and then iteratively add the widgets with <% scripting.
What is the est way to do this in the current release (5 I believe)?
My solution could be something like this (pseudo-code):
<script language="javascript" type="text/javascript">
var widgets;
$(document).ready(function() {
widgets = 0;
<% for each value in ViewData("WidgetValues") %>
AddWidget(<%= value %>);
<% next %>
});
function AddWidget( value ) {
$('#widgets').append("<li><input type='text' name='widget" + widgets +
"'>" + value + "</input></li>");
widgets++;
}
</script>
<ul id="widgets">
</ul>
And in the controller:
[AcceptVerbs("Post")]
public ActionResult AddWidget(FormCollection form)
{
dim collValues as new Collection;
foreach (string s in form)
{
string t = form[s];
collValues.add( t )
}
ViewData("WidgetValues") = collValues;
return RedirectToAction("ActionName");
}
You can work out the details later
(sorry for mixing VB with C#, I'm a VB guy)
i might be missing the point here, but, do you need to actually post the data back to the controller via a form action? why not make an ajax call using jquery to post the data to the controller...or better yet a web service? send the data async and no need to rebuild the view with the data values sent in.
This works fine if the values are being consumed and never used again, however, if you plan on persisting the data and surfacing it through a the view, your model should really support the data structure. maybe a Dictionary<string, string> on the model.
I'm not a ASP.net developer but I know from PHP that you can use arrays as names for input fields
Ex:
<input type="text" name="widgets[]" />
<input type="text" name="widgets[]" />
You can then iterate through the post variable widgets as if it was an array of values.
No messing around with dynamicaly named variables etc.
As far as I understand the problem is to preserve the posted values in widgets.
I thik you can just render those widgest you wont to populate on the server during the View rendering.

Passing data from View to Controller

In an ASP.NET MVC application, I'm making logic for Admin to accept or reject new members. I'm showing a list of members and two buttons Accept and Reject, like this:
<% foreach (var mm in (ViewData["pendingmembers"] as List<MyMember>)) %>
<% { %>
<tr><td>Username:<%=mm.UserName %></td><td>
<tr><td>Firstname:<%=mm.FirstName %></td><td>
...etc...
<tr>
<td>
<% using (Html.BeginForm("AcceptPendingUser", "Admin"))
{ %>
<input type="submit" value="Accept" />
<% } %>
</td>
<td>
<% using (Html.BeginForm("RejectPendingUser", "Admin"))
{ %>
<input type="submit" value="Reject" />
<% } %>
</td>
</tr>
<% } %>
So, the list of pending member data is in a list of MyMember-objects. Each MyMember object will be printed out member and two buttons are setup for the admin to either accept or reject a pending member.
Then, in the controller I'm separating the handling of those two input fields/forms, like this:
public ActionResult AcceptPendingUser()
{
// TODO: Add code to save user into DB and send welcome email.
return RedirectToAction("Index");
}
public ActionResult RejectPendingUser()
{
// TODO: Add code to remove user from PendingUsers list and send rejection email.
return RedirectToAction("Index");
}
I would like to directly get the object next to the button the user pressed.
How can I send the MyMember object from the View to the controller?
Or how do I send perhaps a numeric index with button press? Maybe with a hidden field?
The simplest option would probably be a hidden input:
<input type="hidden" value="<%=mm.Key%>" name="key" id="key" />
(name accordingly; in each form)
The two controller would then take an argument called "key" (rename to suit). If you want to parse the object from multiple inputs, you'll need a ModelBinder. Of course, rather than 2*n forms, you might consider either query-string based urls, or use something like jQuery (or some other script helper) to submit the data without needing the forms (if script is available).
Instead of using an HTML button consider using an ActionLink and construct it to include the id of the member being approved. Another alternative would be to have a checkbox (whose value is the id of the member being approved) that the admin can select for each member to be approved and a similar one for reject and one each approve/reject buttons for the entire form.
Answering to myself and other mvc newbies:
I got it finally working with this code:
VIEW:
<%=Html.ActionLink(
"Jump",
"Jump",
new { name=(ViewData["Person"] as Person).Name,
person=ViewData["Person"]},
null) %>
CONTROLLER:
public ActionResult Index()
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
Person p = new Person();
p.Name = "Barrack";
p.Age = 35;
ViewData["Person"] = p;
return View();
}
public ActionResult Jump(string name, Person person)
{
return View();
}
Debugging the app in the Jump method gives me nice "Barrack"-string for the name parameter, but Person parameter in null.
I also understand what the kind commenters tried to explain: it's easy to send simple data types like strings and ints to controller, but complex types such as my Person object needs something else.
Basically passing an int is enough for me. The hardest part here was figuring out the right way to set up ActionLink.
Cheers,
Pom

Categories