In a cshtml page I'm able to select a class in function of a database value. Example:
<div class="alert #item.State" role="alert">#item.State</div>
"State" is an enum of my table defined as follow:
public enum States
{
Ready,
Setup,
Pause,
Error,
Maintenance,
Emergency,
Disconnected
}
the Razor syntax above will add a class to my alert in function of the item value. Good!
But now I need to "translate" this class to Bootstrap's one. Example:
Ready: alert-primary
Pause or Disconnected: alert-secondary
Error: alert-danger
etc...
I'm able to this manually with Razor, but I wonder if there's a convenient way to this directly in css, something like (metacode):
.Ready {
return alert-primary
}
.Pause, .Disconnect {
return alert-secondary
}
You can declare an array of strings which will contain the class names:
string[] ClassList = new string[]
{
"ReadyClass", "SetupClass", "PauseClass", "ErrorClass", "MaintenanceClass", "EmergencyClass", "DisconnectedClass"
};
Now you can display the equivalent class name using the following line
#ClassList[(int)item.State]
I did not test it but it should work.
Related
I have a Blazor page which display a list of components based on a list on which I dynamically add/remove items :
<TelerikButton OnClick="() => State.AddSymbols(SymbolToAdd)">Add</TelerikButton>
#foreach (var symbolToDisplay in State.SymbolsToDisplay)
{
<StockGraph SymbolToDisplay="#symbolToDisplay" OnRemoved="() => State.RemoveSymbol(symbolToDisplay)"/>
}
This is the code of the state :
public void AddSymbols(string symbol)
{
SymbolsToDisplay.Add(symbol);
StateHasChanged();
}
public void RemoveSymbol(string symbol)
{
SymbolsToDisplay.Remove(symbol);
StateHasChanged();
}
And the code of the component :
<div class="stock-graph">
<p>
#companyData?.companyName
</p>
<div>
<TelerikButton class="delete-item" onclick="#OnRemoved">X</TelerikButton>
</div>
<TelerikChart ref="#chart">
<TelerikChartSeriesItems>
<TelerikChartSeries Type="ChartSeriesType.Line" Data="#data.StockValues"
Field="#nameof(StockValueData.StockValue)"
CategoryField="#nameof(StockValueData.Date)">
</TelerikChartSeries>
</TelerikChartSeriesItems>
<TelerikChartValueAxes>
<TelerikChartValueAxis Color="red"></TelerikChartValueAxis>
</TelerikChartValueAxes>
</TelerikChart>
This is supposed to be pretty straightforward. But for some reason when deleting a component it is always the last component displayed that is deleted even if the list has the required value removed and contains all the correct values.
I have a example of this code running on my github : GitHubRepo
Just add random Stock symbols like GOOG, AAPL, ACC
So it turns out that the issue was coming from the way I way initializing/updating the parameter of my component.
OnInitAsync is not run again after you require to update the data in the page and component.
Instead you have to use OnParametersSetAsync in order for the component to update its parameter correctly
I've got some POCO Model classes that I've setup for use with the Entity Framework. I do some validation in my DbContext's ValidateEntity override. I return a DbEntityValidationResult from the ValidateEntity function, and I can see that during run-time I do add some DbValidationErrors. I can even see those errors inside of the ModelState inside of my Controller function, using the following code ...
catch (DbEntityValidationException ex)
{
foreach (var entity in ex.EntityValidationErrors)
{
foreach (var error in entity.ValidationErrors)
{
ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
}
}
}
But for some reason those errors don't show up for the desired property name in the Razor view. I use a view model that looks like the following ...
public class CharacterCreateModel
{
private Character m_character;
#region Properties
public Character Character
{
get
{
return m_character;
}
set
{
m_character = value;
}
}
#endregion
}
And in my Razor view, which is strongly typed using this CharacterCreateModel view mode, I just use the standard #Html.TextBoxFor, etc.
Validation errors coming from the Character model properly display, but validation errors from the ValidateEntity function are not showing up for that property name.
Any idea why not?
You need to include the ValidationMessageFor helper in your code to show model level properties.
You should have
#Html.EditorFor(model => model.Character)
#Html.ValidationMessageFor(model => model.Character)
If this in not showing the errors change the
#Html.ValidationSummary(true)
at the top of your view to
#Html.ValidationSummary(false)
so you can see all the validation errors and make sure they're actually being added correctly.
I'm building an edit screen where a use can edit rows of data. One of the fields is represented by a drop down, and another is an input field named 'value'. Now, depending on the value in the dropdown, I need to have different kinds of input controls for the value input control. Sometimes it should be a text box, others a datetime control (html5 and / or jqUI date picker), and finally a dropdown list containing a fixed set of values ('Yes' / 'No').
So basically sometimes I need to accept any string data, sometimes a date, and sometimes a boolean (but with a select box, not a check box). What's my best option for implementing this? Ideally the value entered would not be lost moving from one kind of input to another, while the user is on this edit page. On post back, I have a single database value to store (its a sql_variant).
Also, I'm using asp.net mvc3 so an ideal solution will work with the normal Html.ValidateFor and Html.ValidationMessageFor methods.
After lot's of time in JSFiddle, I made this solution. And I think it's pretty cool. It wasn't really that hard. and you can adapt it to whatever you need. just click here.
basically I make variables to represent the possible values. then I make a variable to hold the active element.
Whenever the type selector changes, it calls the change() function which uses if() statements to check what was selected, and then it sets the active element accordingly.
And finally, it calls the hide() function which hides the inactive elements.
here is the updated version
RED ALERT: I realized this didn't work in FF (maybe it was just my browser but whatever).
so I fixed it here
The typical way I accomplish something like this is to actually store 3 different fields in the db for each of the different types of values. Then I create something like the following html:
<!-- Input type selector -->
<div class="cell variable-selector">
<select><option ...</select>
</div>
<!-- varied input -->
<div class="cell variable show-text">
<div class="text"><input type="textbox"></div>
<div class="date-picker"><input type="textbox" class="datepicker"></div>
<div class="drop-down-bool"><select><option ...</select>
</div>
Then I have css that hides or shows the correct input element based on which class the cell has:
div.variable div { display:none }
div.show-text div.text { display: inline }
div.show-date-picker div.date-picker {display: inline }
div.show-drop-down-bool div.drop-down-bool {display: inline}
lastly you can setup some javascript so that when you change your variable-selector you change the class of your variable cell. Which jquery one might do this as so:
$(document).ready(function() {
var variableSelector = $("div.variable-selector > select");
variableSelector.change(function() {
var type = $(this).text();
var class = "cell variable show-" + type;
var variableCell = $(this).parent().parent().find("variable");
variableCell.attr("class", class);
})
});
As a quick warning I wrote the above code on the fly in the stack overflow editor window so there might be a couple of syntax errors or a minor bug somewhere but the basic idea should work. Hope it helps.
--Adam
In case you want to make full use of mvc3 validations, consider this approach.
Model
public class MultiValueViewModel
{
[Required]
public string TextValue { get; set; }
[Required]
public bool? BooleanValue { get; set; }
public MultiValueType ValueType { get; set; }
}
public enum MultiValueType
{
Text,
Boolean
}
View
#model MultiValueViewModel
#Html.DropDownListFor(m => m.ValueType, new SelectList(new[]
{
MultiValueType.Text,
MultiValueType.Boolean
}), new { #id = "multi_value_dropdown" })
<p>
<div data-type="#MultiValueType.Text" class="multi-value-pane">
#Html.EditorFor(m => m.TextValue)
</div>
<div style="display: none" data-type="#MultiValueType.Boolean" class="multi-value-pane">
#Html.DropDownListFor(m => m.BooleanValue, new SelectList
(new [] {
new SelectListItem { Text = "Yes", Value = "true"},
new SelectListItem { Text = "No", Value = "false"}
}, "Value", "Text"), optionLabel: "[Not Set]")
</div>
</p>
Javascript:
<script type="text/javascript">
$(function () {
$("#multi_value_dropdown").change(function () {
var value = $(this).val();
$(".multi-value-pane").each(function () {
$(this).css("display", value == $(this).attr("data-type") ? "block" : "none");
});
});
})
Inside your controller, receive MultiValueViewModel value (alone or inside parent model), and based on selected ValueType save to database. Please note that you will need jquery.validate version 1.9 if you need to skip validation on hidden fields (e.g. :hidden).
I'm strugling on this for quite a while now. I need to create a custom mvc3 html helper for easy filter and toolbar management.
All that helper should look something like this below or something similar. What i want to do is to have a helper where i could give toolbar buttons and filter fields and it generate a toolbar and filter form for me.
I just can't figure it out, because i'm quite new in asp.net mvc
#Html.Toolbar(x => {
x.AddFilterButton();
x.AddButton("Naujas");
x.AddDropDownList();
},
#<text>
#Html.EditorFor(Model.ListFilter.Name)
Filter
ResetFilter
</text>,
filterVisible: false)
How i could achieve this? Any help would be highly apreciated. Thanks indeed.
Something like this:
public static class ToolbarExtensions {
public static Toolbar Toolbar<T>(this HtmlHelper<T> html) {
return new Toolbar();
}
}
public class Toolbar : IHtmlString {
public string ToHtmlString() { /* build your HTML off the state here */ }
public Toolbar AddButton(string label) {
/* build up state here */
return this;
}
}
The syntax on this would be a little different, instead of a lambda, would look like this:
#Html.Toolbar().AddButton("Button 1").AddButton("Button 2")
But you could easily change it to use a chaining object in the lambda instead of on the Toolbar method call.
The IHtmlString interface tells the ViewEngine to output the object as raw HTML when its encountered. The chaining is just achieved by returning the current instance in your methods after modifying the object state.
I've found it's often useful to special case the first item in a drop-down menu (ie, an instance of Menu). For example, if I want to pick a color from the list provided by a web service:
<mx:PopUpMenuButton id="colorSelelector"
dataProvider="{colorsService.lastResult}" />
I might also want a special-case, which is "enter a new color", allowing the user to enter the RGB values for a new color which isn't in the list. For example:
var newColor = { label: "Enter a new color", rgb: null };
Then used with:
<mx:PopUpMenuButton id="colorSelelector"
dataProvider="{colorsService.lastResult}"
lastOption="{newColor}" />
So, apart from changing the list I get back from the service, is there any better way to do this?
(and just a preemptive comment: this is a simplification… I'm not actually trying to make a color-picking-list)
When you bind to the dataProvider, call a function that adds your special case. For instance:
<mx:PopUpMenuButton id="colorSelector"
dataProvider="{addSpecialCases(colorsService.lastResult)}"/>
So, apart from changing the list I get
back from the service, is there any
better way to do this?
This approach is going to be the cleanest, without extending HTTPService, which would work well (but is really just altering your result ;) ):
package
{
import mx.rpc.http.HTTPService;
public class MyHTTPService extends HTTPService
{
public var appendToResult:Object;
public function MyHTTPService(rootURL:String=null, destination:String=null)
{
super(rootURL, destination);
}
[Bindable("resultForBinding")]
override public function get lastResult():Object
{
//I know what my type is, Array as an example
var myResult:Array = operation.lastResult;
myResult.push( this.appendToResult )
return myResult;
}
}
}