toastr js is not showing toasts - asp.net-mvc-3

I am using toastr.js for notification, my drop down code is
<%= Html.DropDownListFor(m => m.MakeText, Model.MakeSelect, string.Empty, new { data_bind = "optionsText: Make,value: Make", Id = "ddMake", style = "width: 200px;font-size: 20px" })%>
and in site typescript is
$(document).ready(function () {
viewModel.Make.subscribe(function (item) {
item && toastr.success('selected make');
});
)}
but problem is i can not see toasts, once i implement only
toastr.success('selected make')
its work good, Can you please tell me what is the issue in subscribe code.
Thanks

item is falsy. That would mean item && toastr.success('selected make'); gets short-circuited and toastr.success('selected make'); is never evaluated.

Related

Run script on loading DropDownListFor

I have a view with the following line of code:
#Html.DropDownListFor(m => m.FrequencyTypes, (List<SelectListItem>)ViewBag.FreqTypes, null, new { #onchange = "toggleOptionalDisplay(this.value)", #class = "form-control" })
This works great for when the drop down is changed but I can't work out how to run the script when the drop down is first loaded.
I got this working by changing the drop down to:
#Html.DropDownListFor(m => m.FrequencyTypes, (List<SelectListItem>)ViewBag.FreqTypes, null, new { #onchange = "toggleOptionalDisplay(this.value)", #class = "form-control", #id = "freqtype", #style = "width:300px;" })
and adding the following extra script (which calls my original function):
<script>
$(document).ready(function () {
toggleOptionalDisplay($("#freqtype").val());
})
</script>
I think this could helped you, but this approach uses jQuery
$(document).ready(function() {
$('select[name="FrequencyTypes"]').change();
});

Kendo UI / MVC - Getting a Menu item to open in a Tab page instead of calling Action, using onclick?

I have a Kendo UI menu:
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("About").Action("Index", "Home");
}))
Instead of loading the new page with an Action I want to call a javascript function onclick. How can I do this? Should I use the HtmlAttributes property?
Additionally, I'm using the moonlight theme which has white menu item text for non-actions and orange text for action menu items. For my menu item which will call the javascript function how would I keep this as orange text? By setting a style, or is there another way?
My sample code is on http://www.eeedee.com if I haven't explained myself well enough.
Thanks
You can work with andrewdudek84 answer(That way is really great).
There is two more solution (The hacking way):
Solution 1
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("About").Url("javascript:void(0)")
.HtmlAttributes(new {
#class= "helloWorld"
});
}))
<script>
$('.helloWorld').click(function(){
//put your code here
});
</script>
Solution 2
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("About").Action("Index", "Home")
.HtmlAttributes(new {
#class= "helloWorld"
});
}))
<script>
$('.helloWorld').click(function(e){
e.preventDefault(); // Cancel the default action of your click.
//put your code here
});
</script>
I would suggest something like this:
<ul id="menu">
<li id="menuItem1">Menu Item 1</li>
</ul>
<script type="text/javascript">
$(document).ready(function() {
$("#menu").kendoMenu({
select: menuItemSelect,
theme: "Moonlight"
});
});
function menuItemSelect(e){
alert(e.item.id);
}
</script>
You can also use the "LinkHtmlAttributes" to, um, add attributes to the generated link:
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add()
.Text("About")
.Action("Index", "Home")
.LinkHtmlAttributes(new { id = "myLink", onclick = "return OnMyLinkClick();" });
}))
Slightly off topic, but for anyone looking to call an action method from the menu, but have the target page open in a new tab...
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add()
.Text("About")
.Action("Index", "Home")
.LinkHtmlAttributes(new { target = "_blank" });
}))

checkbox value is always true

in my mvc application i have a checkbox. but dont know why its value is always true. pls help
my view page
<div id="maindiv">
<%: Html.CheckBoxFor(m => m.status)%>
<%: Html.LabelFor(m => m.status)%>
</div>
and the script is here how i am getting the value TRUE always
<script type="text/javascript">
$('#status').change(function () {
alert(" active " + $('#status').val());
});
</script>
use instead:
var status = ( $("#status").attr("checked") ? 'checked' : 'unchecked' );
alert(" active " + status);
Explanation:
you were reading the value of the checkbox which is always true, you need to check whether its checked attribute is checked or unchecked.
I used the ternary operator to check check whether it's checked or not
You could have also used $("#status").is(":checked") but it is slower.
$('#status').change(function () {
alert(" active " + this.checked);
});
I recommend this answer by Jab because it works.
var myValue = $("#status").is(":checked");
If checked, myValue = true, else myValue = false.

Knockout.js wizard validation on each step

I have managed to create a simple wizard based on an answer given by Niemeyer. This works fine. I want to add validation. I have managed to add a required validion on the field Firstname. Leaving this empty displays an error. But what I could not succeed in is the following:
Validate the model in the current step, and have the go next enabled or disabled based whether there are errors. If it is too difficult to enable or disable the next button, that is ok. I can also live without the button disabled when there are errors. As long as the user is prevented to proceed to the next step when there are errors.
. My view looks like this:
//model is retrieved from server model
<script type="text/javascript">
var serverViewModel = #Html.Raw(Json.Encode(Model));
</script>
<h2>Test with wizard using Knockout.js</h2>
<div data-bind="template: { name: 'currentTmpl', data: currentStep }"></div>
<hr/>
<button data-bind="click: goPrevious, enable: canGoPrevious">Previous</button>
<button data-bind="click: goNext, enable: canGoNext">Next</button>
<script id="currentTmpl" type="text/html">
<h2 data-bind="text: name"></h2>
<div data-bind="template: { name: getTemplate, data: model }"></div>
</script>
<script id="nameTmpl" type="text/html">
<fieldset>
<legend>Naamgegevens</legend>
<p data-bind="css: { error: FirstName.hasError }">
#Html.LabelFor(model => model.FirstName)
#Html.TextBoxFor(model => model.FirstName, new { data_bind = "value: FirstName, valueUpdate: 'afterkeydown'"})
<span data-bind='visible: FirstName.hasError, text: FirstName.validationMessage'> </span>
</p>
#Html.LabelFor(model => model.LastName)
#Html.TextBoxFor(model => model.LastName, new { data_bind = "value: LastName" })
</fieldset>
</script>
<script id="addressTmpl" type="text/html">
<fieldset>
<legend>Adresgegevens</legend>
#Html.LabelFor(model => model.Address)
#Html.TextBoxFor(model => model.Address, new { data_bind = "value: Address" })
#Html.LabelFor(model => model.PostalCode)
#Html.TextBoxFor(model => model.PostalCode, new { data_bind = "value: PostalCode" })
#Html.LabelFor(model => model.City)
#Html.TextBoxFor(model => model.City, new { data_bind = "value: City" })
</fieldset>
</script>
<script id="confirmTmpl" type="text/html">
<fieldset>
<legend>Naamgegevens</legend>
#Html.LabelFor(model => model.FirstName)
<b><span data-bind="text:NameModel.FirstName"></span></b>
<br/>
#Html.LabelFor(model => model.LastName)
<b><span data-bind="text:NameModel.LastName"></span></b>
</fieldset>
<fieldset>
<legend>Adresgegevens</legend>
#Html.LabelFor(model => model.Address)
<b><span data-bind="text:AddressModel.Address"></span></b>
<br/>
#Html.LabelFor(model => model.PostalCode)
<b><span data-bind="text:AddressModel.PostalCode"></span></b>
<br/>
#Html.LabelFor(model => model.City)
<b><span data-bind="text:AddressModel.City"></span></b>
</fieldset>
<button data-bind="click: confirm">Confirm</button>
</script>
<script type='text/javascript'>
$(function() {
if (typeof(ViewModel) != "undefined") {
ko.applyBindings(new ViewModel(serverViewModel));
} else {
alert("Wizard not defined!");
}
});
</script>
The knockout.js implementation looks like this:
function Step(id, name, template, model) {
var self = this;
self.id = id;
self.name = ko.observable(name);
self.template = template;
self.model = ko.observable(model);
self.getTemplate = function() {
return self.template;
};
}
function ViewModel(model) {
var self = this;
self.nameModel = new NameModel(model);
self.addressModel = new AddressModel(model);
self.stepModels = ko.observableArray([
new Step(1, "Step1", "nameTmpl", self.nameModel),
new Step(2, "Step2", "addressTmpl", self.addressModel),
new Step(3, "Confirmation", "confirmTmpl", {NameModel: self.nameModel, AddressModel:self.addressModel})]);
self.currentStep = ko.observable(self.stepModels()[0]);
self.currentIndex = ko.dependentObservable(function() {
return self.stepModels.indexOf(self.currentStep());
});
self.getTemplate = function(data) {
return self.currentStep().template();
};
self.canGoNext = ko.dependentObservable(function () {
return self.currentIndex() < self.stepModels().length - 1;
});
self.goNext = function() {
if (self.canGoNext()) {
self.currentStep(self.stepModels()[self.currentIndex() + 1]);
}
};
self.canGoPrevious = ko.dependentObservable(function() {
return self.currentIndex() > 0;
});
self.goPrevious = function() {
if (self.canGoPrevious()) {
self.currentStep(self.stepModels()[self.currentIndex() - 1]);
}
};
}
NameModel = function (model) {
var self = this;
//Observables
self.FirstName = ko.observable(model.FirstName).extend({ required: "Please enter a first name" });;
self.LastName = ko.observable(model.LastName);
return self;
};
AddressModel = function(model) {
var self = this;
//Observables
self.Address = ko.observable(model.Address);
self.PostalCode = ko.observable(model.PostalCode);
self.City = ko.observable(model.City);
return self;
};
And I have added an extender for the required validation as used in the field Firstname:
ko.extenders.required = function(target, overrideMessage) {
//add some sub-observables to our observable
target.hasError = ko.observable();
target.validationMessage = ko.observable();
//define a function to do validation
function validate(newValue) {
target.hasError(newValue ? false : true);
target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
}
//initial validation
validate(target());
//validate whenever the value changes
target.subscribe(validate);
//return the original observable
return target;
};
This was a tricky one, but I'll offer a couple of solutions for you...
If you simply want to prevent the Next button from proceeding with an invalid model state, then the easiest solution I found is to start by adding a class to each of the <span> tags that are used for displaying the validation messages:
<span class="validationMessage"
data-bind='visible: FirstName.hasError, text: FirstName.validationMessage'>
(odd formatting to prevent horizontal scrolling)
Next, in the goNext function, change the code to include a check for whether or not any of the validation messages are visible, like this:
self.goNext = function() {
if (
(self.currentIndex() < self.stepModels().length - 1)
&&
($('.validationMessage:visible').length <= 0)
)
{
self.currentStep(self.stepModels()[self.currentIndex() + 1]);
}
};
Now, you may be asking "why not put that functionality in the canGoNext dependent observable?", and the answer is that calling that function wasn't working like one might thing it would.
Because canGoNext is a dependentObservable, its value is computed any time the model that it's a member of changes.
However, if its model hasn't changed, canGoNext simply returns the last calculated value, i.e. the model hasn't changed, so why recalculate it?
This wasn't vital when only checking whether or not there were more steps remaining, but when I tried to include validation in that function, this came into play.
Why? Well, changing First Name, for example, updates the NameModel it belongs to, but in the ViewModel, self.nameModel is not set as an observable, so despite the change in the NameModel, self.nameModel is still the same. Thus, the ViewModel hasn't changed, so there's no reason to recompute canGoNext. The end result is that canGoNext always sees the form as valid because it's always checking self.nameModel, which never changes.
Confusing, I know, so let me throw a bit more code at you...
Here's the beginning of the ViewModel, I ended up with:
function ViewModel(model) {
var self = this;
self.nameModel = ko.observable(new NameModel(model));
self.addressModel = ko.observable(new AddressModel(model));
...
As I mentioned, the models need to be observable to know what's happening to them.
Now the changes to the goNext and goPrevious methods will work without making those models observable, but to get the true real-time validation you're looking for, where the buttons are disabled when the form is invalid, making the models observable is necessary.
And while I ended up keeping the canGoNext and canGoPrevious functions, I didn't use them for validation. I'll explain that in a bit.
First, though, here's the function I added to ViewModel for validation:
self.modelIsValid = ko.computed(function() {
var isOK = true;
var theCurrentIndex = self.currentIndex();
switch(theCurrentIndex)
{
case 0:
isOK = (!self.nameModel().FirstName.hasError()
&& !self.nameModel().LastName.hasError());
break;
case 1:
isOK = (!self.addressModel().Address.hasError()
&& !self.addressModel().PostalCode.hasError()
&& !self.addressModel().City.hasError());
break;
default:
break;
};
return isOK;
});
[Yeah, I know... this function couples the ViewModel to the NameModel and AddressModel classes even more than simply referencing an instance of each of those classes, but for now, so be it.]
And here's how I bound this function in the HTML:
<button data-bind="click: goPrevious,
visible: canGoPrevious,
enable: modelIsValid">Previous</button>
<button data-bind="click: goNext,
visible: canGoNext,
enable: modelIsValid">Next</button>
Notice that I changed canGoNext and canGoPrevious so each is bound to its button's visible attribute, and I bound the modelIsValid function to the enable attribute.
The canGoNext and canGoPrevious functions are just as you provided them -- no changes there.
One result of these binding changes is that the Previous button is not visible on the Name step, and the Next button is not visible on the Confirm step.
In addition, when validation is in place on all of the data properties and their associated form fields, deleting a value from any field instantly disables the Next and/or Previous buttons.
Whew, that's a lot to explain!
I may have left something out, but here's the link to the fiddle I used to get this working: http://jsfiddle.net/jimmym715/MK39r/
I'm sure that there's more work to do and more hurdles to cross before you're done with this, but hopefully this answer and explanation helps.

jQuery unobtrusive validation in .NET MVC 3 - showing success checkmark

Using jQuery unobtrusive validation within a .NET MVC project and that seems to be working fine. I'm now trying to show a green checkmark when the field validates correctly (client-side and/or remote).
Here's a sample field declaration:
<div class="clearfix">
#Html.LabelFor(model => model.Address1, "Street")
<div class="input">
#Html.TextBoxFor(model => model.Address1, new { #class = "xlarge", #maxlength = "100", #placeholder = "e.g. 123 Main St" })
<span class="help-message">
#Html.ValidationMessageFor(model => model.Address1)
<span class="isaok">Looks great.</span>
</span>
<span class="help-block">Enter the street.</span>
</div>
</div>
What I'd like to do is add a class 'active' to the "span.isaok" which in turn has a checkmark for a background image.
I tried using highlight/unhighlight:
$.validator.setDefaults({
onkeyup: false,
highlight: function (element, errorClass, validClass) {
$(element).addClass(errorClass).removeClass(validClass);
$(element.form).find("label[for=" + element.id + "]").addClass("error");
$(element).parent().find("span.isaok").removeClass("active");
},
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass);
$(element.form).find("label[for=" + element.id + "]").removeClass("error");
if ($(element).val().length > 0) {
$(element).parent().find("span.isaok").addClass("active");
}
}
});
but that shows a green checkmark for all fields even if they're empty! (hence obviously wrong)
I then tried using the 'success' option but that never seems to be fired.
What am I missing?
Edit: So I found this blog post and was able to tap into the success function i.e.
$(function () {
var settings = $.data($('form')[0], 'validator').settings;
settings.onkeyup = false;
settings.onfocusout = function (element) { $(element).valid(); };
var oldErrorFunction = settings.errorPlacement;
var oldSuccessFunction = settings.success;
settings.errorPlacement = function (error, inputElement) {
inputElement.parent().find("span.isaok").removeClass("active");
oldErrorFunction(error, inputElement);
};
settings.success = function (label) {
var elementId = '#' + label.attr("for");
$(elementId).parent().find("span.isaok").addClass("active");
oldSuccessFunction(label);
};
});
but now if the form isn't valid it shows both the error message and the valid mark...
and the latter disappears as soon as I click anywhere on the page.
This appears to be an issue with the jquery.validate.unobtrusive interfering with the settings added later in $.validator.setDefault. The trick is to load the unobtrusive script after the custom settings. See here and vote to fix it here.
In case any one has a similar problem, I finally got this working by using the un-minified version of jquery.validate.unobtrusive.js and adding my js to the onError and onSuccess methods. Existing code was left as it. Use the re-minified version during deployment.
Thanks.
This is not a direct answer to your question. I am going to offer an alternative approach to this: TwitterBootstrapMVC.
With this library all you'd have to write for each input is:
#Html.Bootstrap().ControlGroup().TextBoxFor(m => m.Address1)
And that's it. You will have label, input, and validation message - all taken care of, without javascript. It generates proper html mark up for you. You just need to make sure that you have proper standard css for classes like .field-validation-error, .field-validation-valid...

Resources