Elm Specify Different Value for Other Item in Model - functional-programming

Just starting and playing around with Elm.
I have the following Elm Code:
import Html exposing (..)
import Html.Attributes
import Html.Events exposing (..)
import List
import Random
import Svg exposing (..)
import Svg.Attributes exposing (..)
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ dieFace1 : Int
, dieFace2: Int
}
init : ( Model, Cmd Msg )
init =
( Model 2 5, Cmd.none )
-- UPDATE
type Msg
= Roll
| NewFace Int
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Roll ->
( model, Random.generate NewFace (Random.int 1 6) )
NewFace newFace ->
( Model newFace newFace, Cmd.none )
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Html Msg
view model =
div []
[ h1 [] [ Html.text (toString (model.dieFace1 + model.dieFace2)) ]
, svg
[ width "120", height "120", viewBox "0 0 120 120", fill "white", stroke "black", strokeWidth "3", Html.Attributes.style [ ( "padding-left", "20px" ) ] ]
(List.append
[ rect [ x "1", y "1", width "100", height "100", rx "25", ry "25" ] [] ]
(svgCirclesForDieFace model.dieFace1)
)
, svg
[ width "120", height "120", viewBox "0 0 120 120", fill "white", stroke "black", strokeWidth "3", Html.Attributes.style [ ( "padding-left", "20px" ) ] ]
(List.append
[ rect [ x "1", y "1", width "100", height "100", rx "25", ry "25" ] [] ]
(svgCirclesForDieFace model.dieFace2)
)
, br [] []
, button [ onClick Roll ] [ Html.text "Roll" ]
]
svgCirclesForDieFace : Int -> List (Svg Msg)
svgCirclesForDieFace dieFace =
case dieFace of
1 ->
[ circle [ cx "50", cy "50", r "10", fill "black" ] [] ]
2 ->
[ circle [ cx "25", cy "25", r "10", fill "black" ] []
, circle [ cx "75", cy "75", r "10", fill "black" ] []
]
3 ->
[ circle [ cx "25", cy "25", r "10", fill "black" ] []
, circle [ cx "50", cy "50", r "10", fill "black" ] []
, circle [ cx "75", cy "75", r "10", fill "black" ] []
]
4 ->
[ circle [ cx "25", cy "25", r "10", fill "black" ] []
, circle [ cx "75", cy "25", r "10", fill "black" ] []
, circle [ cx "25", cy "75", r "10", fill "black" ] []
, circle [ cx "75", cy "75", r "10", fill "black" ] []
]
5 ->
[ circle [ cx "25", cy "25", r "10", fill "black" ] []
, circle [ cx "75", cy "25", r "10", fill "black" ] []
, circle [ cx "25", cy "75", r "10", fill "black" ] []
, circle [ cx "75", cy "75", r "10", fill "black" ] []
, circle [ cx "50", cy "50", r "10", fill "black" ] []
]
6 ->
[ circle [ cx "25", cy "20", r "10", fill "black" ] []
, circle [ cx "25", cy "50", r "10", fill "black" ] []
, circle [ cx "25", cy "80", r "10", fill "black" ] []
, circle [ cx "75", cy "20", r "10", fill "black" ] []
, circle [ cx "75", cy "50", r "10", fill "black" ] []
, circle [ cx "75", cy "80", r "10", fill "black" ] []
]
_ ->
[ circle [ cx "50", cy "50", r "50", fill "red", stroke "none" ] [] ]
It renders two dice SVG items, with values 2 and 5 displayed.
With the Roll function, I am trying to get a random number to display for each dice. Right now, what's happening is that both dice are getting the same value. I am not quite sure how to have different random number assigned to each dice.
Appreciate any ideas. Thanks.

You can use Random.pair to generate a 2-tuple of values. You'll need to update NewFace to store a 2-tuple of Int values:
| NewFace (Int, Int)
And then modify update like this:
Roll ->
( model, Random.generate NewFace (Random.pair (Random.int 1 6) (Random.int 1 6))
NewFace (a, b) ->
( Model a b, Cmd.none )

Related

Converting separate data frames to a JSON file for a tidy tree chart

I did not know how to store complex tidy tree data in excel, so I decided to store data for each level in a sheet.
For a simple example, consider the two following dataframes.
for making a tidy tree chart from this dataframes I have tried the following step:
Data
dim_data <- structure(list(dim1 = c("sub1", "sub2", "sub3"), dim2 = c("sub4",
"sub5", NA)), row.names = c(NA, -3L), class = c("tbl_df", "tbl",
"data.frame"))
sub_data <- structure(list(sub1 = c("a", "b", "c"), sub2 = c("d", "f", NA
), sub3 = c("e", "h", NA), sub4 = c("i", "g", NA), sub5 = c("k",
"p", NA)), row.names = c(NA, -3L), class = c("tbl_df", "tbl",
"data.frame"))
Code:
## Function to make each column a list and remove `na`.
list_remove_na <- function(x){
x <- lapply(x, as.list)
x <- sapply(x, function(x) x[!is.na(x)])
x <- sapply(x, unlist)
return(x)
sub_list <- list_remove_na(sub_data)
attach(sub_list)
data_list <- list_remove_na(dim_data)
## Making final list
integrate <- function(x){sapply(x, function(x){ x = get(x)},simplify = F)}
final_list <- sapply(data_list, integrate, simplify = F)
Final list:
final_list
$dim1
$dim1$sub1
[1] "a" "b" "c"
$dim1$sub2
[1] "d" "f"
$dim1$sub3
[1] "e" "h"
$dim2
$dim2$sub4
[1] "i" "g"
$dim2$sub5
[1] "k" "p"
Converting the final list to JSON
library(rjson)
jdata <-toJSON(final_list, indent=1, method="C")
write(jdata, file = "data.json")
JSON File:
{
"dim1":{
"sub1":[
"a",
"b",
"c"
],
"sub2":[
"d",
"f"
],
"sub3":[
"e",
"h"
]
},
"dim2":{
"sub4":[
"i",
"g"
],
"sub5":[
"k",
"p"
]
}
}
Then Using following function from here to make a Parents and children JSON data:
const treeify = (orig, parent) => Object.entries(orig).map(
([k, v]) => (Object.assign({name: k, parent}, typeof v == 'object'
? {children: treeify(v, k)}
: {children: {name: v, parent: k}}
))
)
const convert = (orig) => treeify({Root: orig}, 'null')[0]
const orig =
{
"dim1":{
"sub1":[
"a",
"b",
"c"
],
"sub2":[
"d",
"f"
],
"sub3":[
"e",
"h"
]
},
"dim2":{
"sub4":[
"i",
"g"
],
"sub5":[
"k",
"p"
]
}
}
console.log(convert(orig))
Result:
{
"name": "Root",
"parent": "null",
"children": [
{
"name": "dim1",
"parent": "Root",
"children": [
{
"name": "sub1",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub1",
"children": {
"name": "a",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub1",
"children": {
"name": "b",
"parent": "1"
}
},
{
"name": "2",
"parent": "sub1",
"children": {
"name": "c",
"parent": "2"
}
}
]
},
{
"name": "sub2",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub2",
"children": {
"name": "d",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub2",
"children": {
"name": "f",
"parent": "1"
}
}
]
},
{
"name": "sub3",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub3",
"children": {
"name": "e",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub3",
"children": {
"name": "h",
"parent": "1"
}
}
]
}
]
},
{
"name": "dim2",
"parent": "Root",
"children": [
{
"name": "sub4",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub4",
"children": {
"name": "i",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub4",
"children": {
"name": "g",
"parent": "1"
}
}
]
},
{
"name": "sub5",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub5",
"children": {
"name": "k",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub5",
"children": {
"name": "p",
"parent": "1"
}
}
]
}
]
}
]
}
I do not know where "name": "0" is come from!!!
And tidy tree from here
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Collapsible Tree Example</title>
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text { font: 12px sans-serif; }
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
</head>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var treeData = [
{
"name": "Root",
"parent": "null",
"children": [
{
"name": "dim1",
"parent": "Root",
"children": [
{
"name": "sub1",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub1",
"children": {
"name": "a",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub1",
"children": {
"name": "b",
"parent": "1"
}
},
{
"name": "2",
"parent": "sub1",
"children": {
"name": "c",
"parent": "2"
}
}
]
},
{
"name": "sub2",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub2",
"children": {
"name": "d",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub2",
"children": {
"name": "f",
"parent": "1"
}
}
]
},
{
"name": "sub3",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub3",
"children": {
"name": "e",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub3",
"children": {
"name": "h",
"parent": "1"
}
}
]
}
]
},
{
"name": "dim2",
"parent": "Root",
"children": [
{
"name": "sub4",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub4",
"children": {
"name": "i",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub4",
"children": {
"name": "g",
"parent": "1"
}
}
]
},
{
"name": "sub5",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub5",
"children": {
"name": "k",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub5",
"children": {
"name": "p",
"parent": "1"
}
}
]
}
]
}
]
}
];
// ************** Generate the tree diagram *****************
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[0];
update(root);
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });
// Declare the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")"; });
nodeEnter.append("circle")
.attr("r", 10)
.style("fill", "#fff");
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -13 : 13; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1);
// Declare the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", diagonal);
}
</script>
</body>
</html>
The last level nodes are wrong!!!
Anybody has suggestions for fixing the problems or alternative solutions in R or Python?
Is there R or Python function to convert raw JSON to hierarchical parent and children Json?
How can I rewrite the R function to convert more than two dataframes (scaling it)?
**I have limited knowledge aboutjavascript and JSON
I'll provide a solution for your case of two data frames, but I'd like to find out whether you can store the data in a different format (which can be expanded to more dimensions). I'll illustrate below what I mean.
First, I'll load two packages. The first one (data.table) will help with the data.wrangling, whereas the second (collapsibleTree) will help with the tree visualization:
# Load packages
library(data.table)
library(collapsibleTree)
Next I convert the datasets to data.table as I want to re-format them:
# Convert datasets to data.table format
setDT(sub_data)
setDT(dim_data)
I now convert them to (what is called) 'long' format by using the melt function:
# Convert to long format
sub_data_2 = melt.data.table(sub_data, measure.vars = colnames(sub_data))
dim_data_2 = melt.data.table(dim_data, measure.vars = colnames(dim_data))
At this point, I have sub_data_2:
variable value
1: sub1 a
2: sub1 b
3: sub1 c
4: sub2 d
5: sub2 f
6: sub2 <NA>
7: sub3 e
8: sub3 h
9: sub3 <NA>
10: sub4 i
11: sub4 g
12: sub4 <NA>
13: sub5 k
14: sub5 p
15: sub5 <NA>
and dim_data_2:
variable value
1: dim1 sub1
2: dim1 sub2
3: dim1 sub3
4: dim2 sub4
5: dim2 sub5
6: dim2 <NA>
Next, we merge them:
# Merge
merged = merge(dim_data_2, sub_data_2, by.x = "value", by.y = "variable")
Then do some clean up by renaming columns, and removing those rows with NA entries:
# Cleanup
setnames(merged, colnames(merged), c("sub", "dim", "value"))
merged_2 = merged[complete.cases(merged),]
This is the format I was referring to above:
sub dim value
1: sub1 dim1 a
2: sub1 dim1 b
3: sub1 dim1 c
4: sub2 dim1 d
5: sub2 dim1 f
6: sub3 dim1 e
7: sub3 dim1 h
8: sub4 dim2 i
9: sub4 dim2 g
10: sub5 dim2 k
11: sub5 dim2 p
Is it possible for you to save in this format? Most of what I've done so far is data wrangling. As you will see below, once I have this format, tree plotting is one line of code:
collapsibleTree(merged_2, c("dim", "sub", "value"), collapsed = F)

Elm Language, mouse tracer

I am trying to make a simple mouse follower. A blue circle who's position updates with my mouse position. What is wrong with my update and view that won't allow this?
type alias Model = { position : { x : Int, y : Int} }
update : Msg -> Model -> (Model,Cmd.Cmd Msg)
update (MouseMsg pos) model = ({ position = {x = model.position.x + pos.x, y = model.position.y + pos.y} },Cmd.none)
view : Model -> Html.Html Msg
view model = let
posX = toString model.position.x
posY = toString model.position.y
in
svg [width "600",height "600"] [circle [cx "300",cy "300", r "50", fill "blue", x posX, y posY] []]
The <circle> SVG element does not support x or y attributes (they're silently ignored). cx and cy are the coordinates of the center, so you need to pass posX and posY to them:
Change:
circle [cx "300",cy "300", r "50", fill "blue", x posX, y posY]
To:
circle [cx posX, cy posY, r "50", fill "blue"]

Add a horizontal discrete legend below the chart in ggvis

I'd like to make a horizontal legend below the ggvis chart. I can use legend properties to place it below the chart, but don't know how to make the labels horizontal below the legend title. Below is the minimum reproducible code (grabbed from the web).
df1 = data.frame(x=sample(1:10), y=sample(1:10))
df2 = data.frame(x=1:10, y=1:10)
df3 = data.frame(x=1:10, y=sqrt(1:10))
df2$id <- 1
df3$id <- 2
df4 <- rbind(df2,df3)
df4$id <- factor(df4$id)
df4 %>% ggvis(x=~x, y=~y, stroke=~id) %>% layer_lines() %>%
# make sure you use add relative scales
add_relative_scales() %>%
# values for x and y need to be between 0 and 1
# e.g for the x-axis 0 is the at far-most left point and 1 at the far-right
add_legend("stroke", title="Cylinders",
properties=legend_props(
legend=list(
x=scaled_value("x_rel", 0.2),
y=scaled_value("y_rel", -.2)
))) %>%
layer_points(x=~x, y=~y, data=df1, stroke:='black')
This is most certainly a hack, but works great:
df4 %>% ggvis(x=~x,y=~y,stroke=~id) %>% layer_lines() %>%
#make sure you use add relative scales
add_relative_scales() %>%
#values for x and y need to be between 0 and 1
#e.g for the x-axis 0 is the at far-most left point and 1 at the far-right
add_legend("stroke", title = "Cylinders", values = c(1, 1),
properties = legend_props(
legend = list(
x = scaled_value("x_rel", 0.2),
y = scaled_value("y_rel", -.2)
))) %>%
add_legend("stroke", title = " ", values = c(2, 2),
properties = legend_props(
legend = list(
x = scaled_value("x_rel", 0.23),
y = scaled_value("y_rel", -.2)
))) %>%
layer_points(x=~x,y=~y,data = df1,stroke:='black')
Basically, I'm adding another add_legend, setting the title as blank, adjusting the scale_value so that it is very close to the first legend but not overlapping. I then set the first legend with values = c(1,1) and the second with values = c(2,2) so that the two values stack on top of each other. This makes it look like one legend with horizontal values.
Seen that ggvis is dormant now, maybe you may consider switching to googleVis.
Here's a similar plot you can get by manipulating a little bit your sample data:
df5 <- df4[df4$id==1,]
colnames(df5)[2] <- "y1"
library(tidyverse)
df5 <- df5 %>%
mutate(
y0 = df1[order(df1$x),c(2)],
y2 = sqrt(x)
)
df5 <- df5[, c(1,4,2,5)]
library(googleVis)
plot_df5 <- gvisLineChart(df5, options=list(
legend="bottom",
series =
"[{labelInLegend: 'Dot', color: 'black'},
{labelInLegend: 'Cylinders: 1', color: 'blue', curveType: 'dot'},
{labelInLegend: 'Cylinders: 2', color: 'orange'}]"
)
)
plot(plot_df5)
<!-- LineChart generated in R 3.5.2 by googleVis 0.6.2 package -->
<!-- Sun Dec 30 21:21:26 2018 -->
<!-- jsHeader -->
<script type="text/javascript">
// jsData
function gvisDataLineChartID1fd8710660d () {
var data = new google.visualization.DataTable();
var datajson =
[
[
"1",
3,
1,
1
],
[
"2",
4,
2,
1.414213562
],
[
"3",
6,
3,
1.732050808
],
[
"4",
1,
4,
2
],
[
"5",
10,
5,
2.236067977
],
[
"6",
8,
6,
2.449489743
],
[
"7",
7,
7,
2.645751311
],
[
"8",
2,
8,
2.828427125
],
[
"9",
9,
9,
3
],
[
"10",
5,
10,
3.16227766
]
];
data.addColumn('string','x');
data.addColumn('number','y0');
data.addColumn('number','y1');
data.addColumn('number','y2');
data.addRows(datajson);
return(data);
}
// jsDrawChart
function drawChartLineChartID1fd8710660d() {
var data = gvisDataLineChartID1fd8710660d();
var options = {};
options["allowHtml"] = true;
options["legend"] = "bottom";
options["series"] = [{labelInLegend: 'Dot', color: 'black'},
{labelInLegend: 'Cylinders: 1', color: 'blue', curveType: 'dot'},
{labelInLegend: 'Cylinders: 2', color: 'orange'}];
var chart = new google.visualization.LineChart(
document.getElementById('LineChartID1fd8710660d')
);
chart.draw(data,options);
}
// jsDisplayChart
(function() {
var pkgs = window.__gvisPackages = window.__gvisPackages || [];
var callbacks = window.__gvisCallbacks = window.__gvisCallbacks || [];
var chartid = "corechart";
// Manually see if chartid is in pkgs (not all browsers support Array.indexOf)
var i, newPackage = true;
for (i = 0; newPackage && i < pkgs.length; i++) {
if (pkgs[i] === chartid)
newPackage = false;
}
if (newPackage)
pkgs.push(chartid);
// Add the drawChart function to the global list of callbacks
callbacks.push(drawChartLineChartID1fd8710660d);
})();
function displayChartLineChartID1fd8710660d() {
var pkgs = window.__gvisPackages = window.__gvisPackages || [];
var callbacks = window.__gvisCallbacks = window.__gvisCallbacks || [];
window.clearTimeout(window.__gvisLoad);
// The timeout is set to 100 because otherwise the container div we are
// targeting might not be part of the document yet
window.__gvisLoad = setTimeout(function() {
var pkgCount = pkgs.length;
google.load("visualization", "1", { packages:pkgs, callback: function() {
if (pkgCount != pkgs.length) {
// Race condition where another setTimeout call snuck in after us; if
// that call added a package, we must not shift its callback
return;
}
while (callbacks.length > 0)
callbacks.shift()();
} });
}, 100);
}
// jsFooter
</script>
<!-- jsChart -->
<script type="text/javascript" src="https://www.google.com/jsapi?callback=displayChartLineChartID1fd8710660d"></script>
<!-- divChart -->
<div id="LineChartID1fd8710660d"
style="width: 500; height: automatic;">
</div>

Creating a populated dropdownlist with items in the view

I'm trying to create a dropdownlist that contains a list of items:
#Html.DropDownList("displayCount", new SelectList(
new[]
{
new SelectListItem { Value = "25", Text = "25" },
new SelectListItem { Value = "50", Text = "50" },
new SelectListItem { Value = "100", Text = "100" },
}
));
When I look at my dropdownlist, it just has 3 options that say "System.Web.Mvc.SelectListItem"
What do I need to do differently here?
Try:
#Html.DropDownList("displayCount", new SelectList(
new[]
{
new SelectListItem { Value = "25", Text = "25" },
new SelectListItem { Value = "50", Text = "50" },
new SelectListItem { Value = "100", Text = "100" },
},
"Value",
"Text"
));
You need to tell the SelectList what fields to use:
new SelectList(..., "Value", "Text")
The reason why you got "System.Web.Mvc.SelectListItem" listed in your dropdown is because you didn't specify which attribute of the List Item you want to use for the Text and Value of the dropdown list. Right now, it is being displayed based on the .ToString() of each item in the list, which returns the full name of the SelectListItem class
#Html.DropDownList("displayCount", new SelectList(
new[]
{
new SelectListItem { Value = "25", Text = "25" },
new SelectListItem { Value = "50", Text = "50" },
new SelectListItem { Value = "100", Text = "100" },
},
"Value",
"Text"
));

ASP.NET MVC 3 How to validate dropdownlist

I want to validate Date field of a birthday selection section. I have a dropdownlist with 1-31 days listed down and the default value is "0" and the text is "Day". Code is below:
public IEnumerable<SelectListItems> Date = new List<SelectListItems>
{
new SelectListItems{Value = "0", Text = "Day", Default = true},
new SelectListItems{Value = "1", Text = "1"},
new SelectListItems{Value = "2", Text = "2"},
new SelectListItems{Value = "3", Text = "3"},
new SelectListItems{Value = "4", Text = "4"},
new SelectListItems{Value = "5", Text = "5"},
new SelectListItems{Value = "6", Text = "6"},
new SelectListItems{Value = "7", Text = "7"},
new SelectListItems{Value = "8", Text = "8"},
new SelectListItems{Value = "9", Text = "9"},
new SelectListItems{Value = "10", Text = "10"},
new SelectListItems{Value = "11", Text = "11"},
new SelectListItems{Value = "12", Text = "12"},
new SelectListItems{Value = "13", Text = "13"},
new SelectListItems{Value = "14", Text = "14"},
new SelectListItems{Value = "15", Text = "15"},
new SelectListItems{Value = "16", Text = "16"},
new SelectListItems{Value = "17", Text = "17"},
new SelectListItems{Value = "18", Text = "18"},
new SelectListItems{Value = "19", Text = "19"},
new SelectListItems{Value = "20", Text = "20"},
new SelectListItems{Value = "21", Text = "21"},
new SelectListItems{Value = "22", Text = "22"},
new SelectListItems{Value = "23", Text = "23"},
new SelectListItems{Value = "24", Text = "24"},
new SelectListItems{Value = "25", Text = "25"},
new SelectListItems{Value = "26", Text = "26"},
new SelectListItems{Value = "27", Text = "27"},
new SelectListItems{Value = "28", Text = "28"},
new SelectListItems{Value = "29", Text = "29"},
new SelectListItems{Value = "30", Text = "30"},
new SelectListItems{Value = "31", Text = "31"}
};
My model is as below:
public class PaxInfoViewModel
{
public bool IsChild
{
get { return Age != null; }
}
[Required(ErrorMessage="Please select the born Month")]
public int BirthYear1 { get; set; }
[Range(2, 12, ErrorMessage="Please select the born Month")]
public int BirthMonth { get; set; }
[Required(ErrorMessage = "Please select the born Date")]
[Range(2, int.MaxValue, ErrorMessage = "Please select the born Date")]
public int BirthDate { get; set; }
}
My View is as below:
<div class="row">
<div class="editor-label control-label">#Html.Label("Child " + i + " Birthday ")</div>
<div class="span1">#Html.DropDownListFor(m => Model.Rooms[roomCount - 1].Children[i - 1].BirthDate, new SelectList(Model.DropDown.Date, "Value", "Text"), new { #class = "mini" })</div>
<div class="span2">#Html.DropDownListFor(m => Model.Rooms[roomCount - 1].Children[i - 1].BirthMonth, new SelectList(Model.DropDown.Month, "Value", "Text"), new { #class = "small" })</div>
<div class="errorformat">#Html.ValidationMessageFor(m => Model.Rooms[roomCount - 1].Children[i - 1].BirthMonth)
#Html.ValidationMessageFor(m => Model.Rooms[roomCount - 1].Children[i - 1].BirthDate)
</div></div>
This Date is need to validate. User must select a value other than the Default value. How can I do that.Please help.
Thank You.
Finally I figured it out. ASP.NET MVC 3 Unobtrusive validation only validate "input" elements.
Therefore I had to do some changes to the jquery.validate.unobtrusive.js code.
Here what i did:
On the jquery.validate.unobtrusive.js file, around code line 173(in my file) you can find this code line : $(selector).find(":input[data-val=true]").each(function (), change it to: $(selector).find("[data-val=true]").each(function ().
Also around line 289 you can find this code line : element = $(options.form).find(":input[name=" + fullOtherName + "]")[0], change it to : element = $(options.form).find("[name=" + fullOtherName + "]")[0]
And in my View file I add the validation attributes to the dropdownlist as below:
#Html.DropDownListFor(Yourmodelvariable, Yourlistitems, new Dictionary<string, object>() { { "data-val-range-min", "1" }, { "data-val-range-max", "31" }, { "data-val-range", "Please select the born Date" }, { "data-val", "true" }, { "class", "mini" } }) "
#Html.ValidationMessageFor(Yourmodelvariable)
You can add the validation attribute as you want to validate(In my case I want to validate a range), and it works for me as smooth as loose motion!.

Resources