Spark View Engine Partial - spark-view-engine

I think I just need someone to show me the obvious.
I have a spark partial
_MessageItem.spark
that is used within a view
like so
<for each="var m in messageList">
<MessageItem message="m"/>
</for>
the partial looks like this:
<tr id="${message.MessageId}">
<td >${message.CreateDate.ToString("M/d/yy h:mm")}</td>
<td >
<b>${message.Subject}</b>
</td>
<td >${message.FromUser.FullName}</td>
<td >${message.ToUser.FullName}</td>
</tr>
<tr>
<td/>
<td colspan="3">${message.Body}</td>
</tr>
works like a champ, except when I try and call the partial directly from an action like so:
public ActionResult GetMessage(Message message)
{
return PartialView("MessageItem",message);
}
When I do the above I get
error CS0103: The name 'message' does not exist in the current context
So my current solution is to create a wrapper partial that feeds the MessageItem partial
like so:
_ActionMessageItem.spark:
<MessageItem message="(Message)ViewData.Model"/>
So can someone state the obvious and tell me how to modify
1) Modify my MessageItem partial so whether being called from PartialView() or within a .spark file it will work
2) Tell me how I need to modify my Controller Action so it won't throw an exception

<viewdata model="Message" message="Message" />
<var msg="message ?? Model" />
Then use the msg variable instead of message (like, ${msg.Subject}, etc).
You may also have luck with adding single
<default message="Model" />
but the first way is the one I think will work.

When you pass parameters PartialView, spark doesn't know anything about your parameter name, only the value that was passed in. So, it uses the name of the argument, which I believe it is model. Since your code is looking for the parameter message it throws an error. I think one solution might be to change to something like this:
<MessageItem model="(Message)ViewData.Model"/>
model may be cased as Model, you'll have to guess and check.

try to call the partial with the underscore and an anonymous object.
ViewData["message"] = message;
return PartialView("_MessageItem");

the problem is that when you call it from the action you're passing data as a Model, but when calling from another view you're passing the data as a parameter. you could only use your data as Model if the other view also shares the same Model object type.
otherwise, what I'd do is pass it in ViewData in your Action:
public ActionResult GetMessage(Message message)
{
ViewData["message"] = message;
return PartialView("MessageItem");
}

Related

How can i solve my this issue in MVC grid Delete Controller

Controller:
public ActionResult Delete(int id)
{
Student _std = new Student();
var abc = _dbcon.StudentList.Where(c => c.Roll_ID.Equals(id)).SingleOrDefault();
_dbcon.StudentList.Remove(abc);
_dbcon.SaveChanges();
return View("Test");
}
This is my view and the error comes at foreach loop
View:
#foreach (StudentViewModel _EachStd in #Model.StudentList)
{
<tr>
<td> #_EachStd.Roll_ID</td>
<td> #_EachStd.Name</td>
<td> #_EachStd.Maths</td>
<td> #_EachStd.Urdu</td>
<td> #_EachStd.English</td>
<td>#_EachStd.ObtainNumber</td>
<td>#_EachStd.Percentage</td>
<td> #_EachStd.Grade</td>
<td>#Html.ActionLink("Edit", "Edit", "Home", new {id= #_EachStd.Roll_ID },null)</td>
<td>#Html.ActionLink("Delete", "Delete", "Home", new { id = #_EachStd.Roll_ID }, null)</td>
</tr>
}
</tbody>
</table>
I got Null Error exception, but after refresh i got the record delete. But why the error occur I dont get It.Whenever i run this code my Edit controller is working correctly but my Delete controller is not working correctly, and error is occur like there is "Null erroe exception"
error is occur like there is "Null erroe exception"
You mean a NullReferenceException? That would mean something is null that you're trying to use as though it has a value.
This is my view and the error comes at foreach loop
So then something on this line is null?:
#foreach (StudentViewModel _EachStd in #Model.StudentList)
The only thing you're trying to dereference on that line is Model. So it follows that Model is null. Are you passing a model to your view?
return View("Test");
No, you are not. You need to pass a model to your view in order to use that model within your view.
As an aside, returning a view from this delete operation probably isn't the way to go in the first place. Consider that the user would now be on the URL /Home/Delete and viewing it as a page. This would quickly get confusing for both the user and your code.
Instead of returning a view, especially one without a model, redirect the user to the action which builds the model and displays the view. Which in your code could be something as simple as:
return RedirectToAction("Test");

Stripes Checkboxes and Textfields

All -
I'm using stripes to do some form input for a problem I'm working on and I'm stuck on how best to submit a a pair of data using stripes and checkboxes.. for example my page looks like the following:
I have a list of options where users can enable a selection by clicking the box, and also supply some input for that item by entering data into the text field next to it:
<tr>
<td><stripes:checkbox name="item.enable" value="${item.id}"/></td>
<td><stripes:text name="item.value" value="${item.value}"/></td>
</tr>
.....
next item...
When the form is submitted I'd expect my Collection<Item> to be populated yet that's not the case..
How can I best submit a pair of items using the check box fields.
Thanks in advance.
..Chris
Read the documentation on indexed properties. You need to tell Stripes that you have multiple items, by naming them items[0], items[1], etc.:
<tr>
<td><stripes:checkbox name="items[0].enable" value="${item.id}"/></td>
<td><stripes:text name="items[0].value" value="${item.value}"/></td>
</tr>
<tr>
<td><stripes:checkbox name="items[1].enable" value="${item.id}"/></td>
<td><stripes:text name="items[1].value" value="${item.value}"/></td>
</tr>
This supposes that you action bean has a setItems(List<Item> items) method, that the Item class has a public no-arg constructor, and has a setEnable(String itemId) and a setValue(String value) method.
I would wrap this in a JSTL 'forEach' tag and I would put the items in a List. Similar to what JB Nizet said, you also need public setters in the action bean. If you are using Collection<Item> with some implementation other than List<Item> the below snippet won't work.
<c:forEach var='itemIndex' begin='0' end='2'>
<c:set scope='page' var='item' value='${items[itemIndex]}'>
<tr>
<td><stripes:checkbox name="items[${itemIndex}].enable" value="${item.id}"/></td>
<td><stripes:text name="items[${itemIndex}].value" value="${item.value}"/></td>
</tr>
</c:forEach>
There is another case when you don't want the list to default to 3 items. The one I'm thinking of is when the list is already populated. If that is the case I would change the 'end' attribute of the <c:forEach> to be: ${fn:length(actionBean.items) == 0 ? 3 : fn:length(actionBean.items)-1}

How to pass both model value & text value to controller in mvc?

I want to pass two values from view to controller . i.e., #Model.idText and value from textbox. here is my code:
#using HTML.BeginForm("SaveData","Profile",FormMethod.Post)
{
#Model.idText
<input type="text" name="textValue"/>
<input type="submit" name="btnSubmit"/>
}
But problem is if i use "Url.ActionLink() i can get #Model.idText . By post action i can get textbox value using FormCollection . But i need to get both of this value either post or ActionLink
using ajax you can achieve this :
don't use form & declare your attributes like this in tags:
#Model.idText
<input type="text" id="textValue"/>
<input type="submit" id="btnSubmit"/>
jquery:
$(function (e) {
// Insert
$("#btnSubmit").click(function () {
$.ajax({
url: "some url path",
type: 'POST',
data: { textField: $('#textValue').val(), idField: '#Model.idText' },
success: function (result) {
//some code if success
},
error: function () {
//some code if failed
}
});
return false;
});
});
Hope this will be helpful.
#using HTML.BeginForm("SaveData","Profile",FormMethod.Post)
{
#Html.Hidden("idText", Model.idText)
#Html.TextBox("textValue")
<input type="submit" value="Submit"/>
}
In your controller
public ActionResult SaveData(String idText, String textValue)
{
return null;
}
I'm not sure which part you are struggling with - submitting multiple values to your controller, or getting model binding to work so that values that you have submitted appear as parameters to your action. If you give more details on what you want to achieve I'll amend my answer accordingly.
You could use a hidden field in your form - e.g.
#Html.Hidden("idText", Model.idText)
Create a rule in global.asax and than compile your your with params using
#Html.ActionLink("My text", Action, Controller, new { id = Model.IdText, text =Model.TextValue})
Be sure to encode the textvalue, because it may contains invalid chars
Essentially, you want to engage the ModelBinder to do this for you. To do that, you need to write your action in your controller with parameters that match the data you want to pass to it. So, to start with, Iridio's suggestion is correct, although not the full story. Your view should look like:
#using HTML.BeginForm("SaveData","Profile",FormMethod.Post)
{
#Html.ActionLink("My text", MyOtherAction, MaybeMyOtherController, new { id = Model.IdText}) // along the lines of dommer's suggestion...
<input type="text" name="textValue"/>
<input type="submit" name="btnSubmit"/>
#Html.Hidden("idText", Model.idText)
}
Note that I have added the #Html.Hidden helper to add a hidden input field for that value into your field. That way, the model binder will be able to find this datum. Note that the Html.Hidden helper is placed WITHIN your form, so that this data will posted to the server when the submit button is clicked.
Also note that I have added dommer's suggestion for the action link and replaced your code. From your question it is hard to see if this is how you are thinking of passing the data to the controller, or if this is simply another bit of functionality in your code. You could do this either way: have a form, or just have the actionlink. What doesn't make sense is to do it both ways, unless the action link is intended to go somewhere else...??! Always good to help us help you by being explicit in your question and samples. Where I think dommer's answer is wrong is that you haven't stated that TextValue is passed to the view as part of the Model. It would seem that what you want is that TextValue is entered by the user into the view, as opposed to being passed in with the model. Unlike idText that IS passed in with the Model.
Anyway, now, you need to set up the other end, ie, give your action the necessary
[HttpPost]
public ActionResult SaveData(int idText, string textValue) // assuming idText is an int
{
// whatever you have to do, whatever you have to return...
}
#dommer doesn't seem to have read your code. However, his suggestion for using the Html.ActionLink helper to create the link in your code is a good one. You should use that, not the code you have.
Recapping:
As you are using a form, you are going to use that form to POST the user's input to the server. To get the idText value that is passed into the View with the Model, you need to use the Html.Hidden htmlhelper. This must go within the form, so that it is also POSTed to the server.
To wire the form post to your action method, you need to give your action parameters that the ModelBinder can match to the values POSTed by the form. You do this by using the datatype of each parameter and a matching name.
You could also have a complex type, eg, public class MyTextClass, that has two public properties:
public class MyTextClass
{
public int idText{get;set}
public string TextValue{get;set;}
}
And then in your controller action you could have:
public ActionResult SaveData(MyTextClass myText)
{
// do whatever
}
The model binder will now be able to match up the posted values to the public properties of myText and all will be well in Denmark.
HTH.
PS: You also need to read a decent book on MVC. It seems you are flying a bit blind.
Another nit pick would be to question the name of your action, SaveData. That sounds more like a repository method. When naming your actions, think like a user: she has simply filled in a form, she has no concept of saving data. So the action should be Create, or Edit, or InformationRequest, or something more illustrative. Save Data says NOTHING about what data is being saved. it could be credit card details, or the users name and telephone...

ASP.Net MVC3 Parent Child Model Binding

I have a partial template that uses a User object as a model. The user has a collection of Accounts. On this partial template I have a loop as follows. The _Account partial template is bound to the Account class
#foreach (var item in Model.Accounts)
{
<tr>
<td colspan="6">
<div>
#Html.Partial("_Account", item)
</div>
</td>
</tr>
}
In my controller method I initially tried
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UserDetails(User user, string actionType)
But the User.Accounts collection is empty. Then I tried this. Still the Accounts collection is empty.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UserDetails(User user,
[Bind(Prefix="User.Accounts")]
FixupCollection<Account> Accounts,
string actionType)
Can I use the default Modelbinder implementation to achieve this or do I need to do anything different?
Yep, you can use the default model binder. You just need to name your fields correctly. So you need your loop to output something like this:
...
<input type="text" name="user.Accounts[0].SomeTextField" />
<input type="text" name="user.Accounts[0].SomeOtherTextField" />
...
<input type="text" name="user.Accounts[1].SomeTextField" />
<input type="text" name="user.Accounts[1].SomeOtherTextField" />
...
If you need to add/remove accounts, the hardcoded indexes get a little trickier. You could re-assign the names using javascript before postback. But it's all possible. This question gives more detail on model binding:
ASP.NET MVC: Binding a Complex Type to a Select
Use Editor Templates instead of a partial view - no need to hard code your indexes as the template will automagically index all your objects correctly, even when you add and remove Accounts. See my answer to this question:
Pass values from multiple partial views
Small write up on Editor Templates here:
codenodes.wordpress.com - MVC3 Editor Templates

Using Beans to populate/retrieve view

I'm new to Spring and little confused of how to use beans for populating and retrieving values to/from the view.
Here is what I'm doing now.
In the controller I'm initializing two beans xxxMain.java and xxxView.java. I'm using xxxMain.java to retrieve values FROM the view and xxxView.java for pre-populating the view.
Here is my controller
#RequestMapping(value = "accounting", method = RequestMethod.GET)
public String showPage( Model model) {
XXXMain xxxMain = new XXXMain();
XXXView xxxView = new XXXView();
service.loadXXXForm(xxxMain, xxxView);
model.addAttribute("xxxMain", xxxMain);
model.addAttribute("xxxView", xxxView);
return "admin/xxx";
}
So as I'm using the xxxMain.java for retrieving I'm coding the jsp like this.
<form:form modelAttribute="XXXMain" method="post" action="/app/home/save">
</form:form>
also I'm using Spring tags, like
<form:input path="name" size="15"/>
Now, when the fields in the view are empty, all is fine, but when I have to pre-populate the fields, I'm not sure what approach to take as
<form:input path="name" size="15"/>
does not has a value attribute to populate the field. So what I have done is populate the XXXMain.java class along with the XXXView.java class with the default values, as you can see in the controller code snippet. That way values are pre-populated when view is first loaded. But I'm not sure if I'm doing the right thing by populating the xxxMain.java file which in fact should only contain the user entered values.
How can I improve this design?
Thanks a lot.
Ravi
Here is an example I wrote which might help steer you right.

Resources