I've been following web tutorials to try to learn angularJS on a .NET MVC Application. All the tutorials seem to cover getting a list, getting an individual item etc.
What I want to do is allow the user to fill in an email address, I want to verify that email address against the database and return true or false if it existed. I'm then trying to put that value in the scope so I can do something in response to whether its true or false.
I'm using a single page app so this is the login html.
<form name="form" class="form-horizontal">
<div class="control-group" ng-class="{error: form.ValidEmailAddress.$invalid}">
<label class="control-label" for="ValidEmailAddress">Valid Email Address</label>
<div class="controls">
<input type="email" ng-model="item.ValidEmailAddress" id="ValidEmailAddress">
</div>
</div>
<div class="form-actions">
<button ng-click="login()" class="btn btn-primary">
Go!
</button>
<label ng-if="user.isAuthorised">Authorised</label>
<label ng-if="!user.isAuthorised">NotAuthorised</label>
</div>
</form>
In my app.js file I declare a loginCtrl controller when the url was /login so that's all fine. The logic that I'm calling on my button click is this:
var LoginCtrl = function ($scope, $location, $http, AuthorisedUser) {
$scope.login = function() {
var isValidUser = $http.get("/AuthorisedUser/IsValidUser/" + $scope.item.ValidEmailAddress);
$scope.user.isAuthorised = isValidUser;
} };
Which is then calling an MVC AuthorisedUserController class method:
public bool IsValidUser(string id)
{
var list = ((IObjectContextAdapter)db).ObjectContext.CreateObjectSet<ApprovedUser>();
var anyItems = list.Any(u => u.ValidEmailAddress == id);
return anyItems;
}
So it vaguely seemed to be working when I put in a value like "aaa" into the textbox. But as soon I try putting in an email address the value is undefined. Maybe I'm supposed to be doing a post but the only thing I can successfully hit my .NET controller with is by using get.
I'm sure I'm missing fundamental knowledge and potentially tackling this in the wrong way.
In case it helps I've created a module and defined factories like this:
var EventsCalendarApp = angular.module("EventsCalendarApp", ["ngRoute", "ngResource"]).
config(function ($routeProvider) {
$routeProvider.
when('/login', { controller: LoginCtrl, templateUrl: 'login.html', login: true }).
otherwise({ redirectTo: '/' });
});
EventsCalendarApp.factory('AuthorisedUser', function ($resource) {
return $resource('/api/AuthorisedUser/:id', { id: '#id' }, { isValidUser: { method: 'GET' } });
});
One of my questions is - should I be accessing the controller method using the $http object, or is there a way of using my factory declaration so that I can go something like:
AuthorisedUser.IsValidUser($scope.item.validEmailAddress)
I know in the tutorial I was following I could do stuff like:
CalendarEvent.save()
to be able to call a CalendarEventController post method.
What i think is, your get() function will return a promise. and you can't assign promise like this. so better try this approch once. I hope, it'd work. if not please let me know...
here I assume your first,second and third snippet of code works fine...
$http.get("/AuthorisedUser/IsValidUser/" + $scope.item.ValidEmailAddress).success(function (result, status) {
var isValidUser=result;
$scope.user.isAuthorised = isValidUser;
$scope.$apply();
}).error(function (result, status) {
//put some error msg
});
Related
I have button: Turn Email On and checkbox (which is unchecked) on side of that button.
When I click Turn email on button,it should call action method of controller where I have to write SP to update the email table.
Email_ON_OFF_T table have one field: isemailon_off(int type). I inserted value 0 into it.
So, Turn email on button's text will become turn email off and checkbox becomes checked.
I have tried the following code:
<div class="col-md-8 form-group" style="text-align:right;">
<input type="button" value="Turn Email ON" class="btn btn-success" id="btnturnemailonoff" />
</div>
<div class="col-md-2 form-group">
<input type="checkbox" id="Chkemailonoff" />
</div>
Ajax code to call button:
$(document).ready(function () {
$('#btnturnemailonoff').on('click', function () {
//var prices = [];
//$('#Chkemailonoff').each(function () {
// prices.push($(this).attr("value"));
//});
var checked = !$(this).data('checked');
$("#Chkemailonoff").prop('checked', checked);
$(this).val(checked ? 'Turn Email Off' : 'Turn Email on')
$(this).data('checked', checked);
debugger;
var url = '#Url.Action("CheckEmail", "BillingDetails")';
$.ajax({
url: url,
type: "POST",
data: { checkemails: checked },
dataType: "json",
// traditional: true,
success: function () {
alert("ajax request to server succeed");
}
});
});
});
From Ajax, I am passing data(view) to the Controllers action Method.
[HttpPost]
public ActionResult CheckEmail(string checkemails)
{
//how to call Stored Procedure
return new JsonResult { };
}
I have written the below SP:
ALTER procedure [dbo].[Sp_Email_on_off]
#checkemails varchar(10)
As
Begin
if(#checkemails='false')
Update Email_ON_OFF_T set isEmailON_OFF=1
else
Update Email_ON_OFF_T set isEmailON_OFF=0
End
The thing where I am stuck is the stored procedure. How to write and execute Sp in Controllers action Method? This is my first task in MVC. How to achieve this using Mvc?
You can use FromSql or ExecuteSqlCommand to execute stored procedure.
FromSql can only be used to execute raw SQL queries or stored procedures to get the data. You can’t use it for INSERT/UPDATE/DELETE. If you want to execute INSERT, UPDATE, DELETE queries, use the ExecuteSqlCommand. It returns integer value which indicates the count of affected rows.
Here is a sample following your requirement. Hope to help, my friend :))
if(!string.IsNullOrWhiteSpace(checkemails))
{
dataContext.Database
.ExecuteSqlCommand("Sp_Email_on_off #checkemails", checkemails);
}
I'm looking for live search for ASP.NET and entity framework. I'm a little bit green with it. I read that it needs to use ajax, but I never used it before and can't get good example. Here is a piece of code, cshtml (part of textbox)
<div class="form-horizontal">
<hr />
<h4>Search for a client: </h4>
<div class="input-group">
<span class="input-group-addon" id="Name">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
</span>
#Html.TextBox("Name", "", new { #class = "form-control", placeholder = "Name" })
</div>
<div><h6></h6></div>
<div class="input-group">
<span class="input-group-addon" id="Surname">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
</span>
#Html.TextBox("Surname", "", new { #class = "form-control", placeholder = "Surname" })
</div>
<div><h6></h6></div>
<button type="submit" class="btn btn-default" data-toggle="modal" data-target="#infoModal">Search</button>
</div>
this is a part of controller:
public ActionResult Index(string Name, string Surname)
{
var SearchList = from m in db.Klienci
select m;
if (!String.IsNullOrEmpty(Name))
{
SearchList = SearchList.Where(s => s.Name.Contains(Name));
}
if (!String.IsNullOrEmpty(Surname))
{
SearchList = SearchList.Where(s => s.Nazwisko.Contains(Surname));
}
return View(SearchList);
}
So it search for me clients by name and surname, but it refresh full page when it lost focus or after clicking the button. How to solve it, to get live search? after each keystroke search through database? I'm a little bit green, would you Help me?
You can listen to the keyup event on your input element, read the value and send it to the server using ajax. Return the results and in the ajax call's success callback, update the ui with the results.
$(function() {
$("#Name,#SurName").keyup(function(e) {
var n = $("#Name").val();
var sn = $("#SurName").val();
$.get("/Home/Index?Name="+n+"&SurName="+sn,function(r){
//update ui with results
$("#resultsTable").html(r);
});
});
});
The code basically listens to the key up event on the two input textboxes and read the values and send to the /Home/Index action method using jquery get method asynchronously.When the action method returns the response, we update the DOM.
Assuming resultsTable is the Id of the table where we list the results.
Also, since you are returning the partial view result ( without layout headers), you should use return PartialView() instead of return View()
if(Request.IsAjaxRequest())
return PartialView(SearchList);
return View(SearchList);
Here is nice example/tutorial how to use Ajax with ASP.NET MVC
http://www.itorian.com/2013/02/jquery-ajax-get-and-post-calls-to.html
EDITED: 2016-07-20
Example:
$(function () {
$("searchField").keyup(function () {
$.ajax({
type: "POST",
url: "/Controller/Action",
data: data,
datatype: "html",
success: function (data) {
$('#result').html(data);
}
});
});
You have to visit the server to get data from server and without ajax it is not possible. Now the question is how to make ajax call, you can use jQuery js lib to do but I would recommend you to try angular as data binding in angular will fulfill your needs.
Take a look at followings links
Angular Ajax Service -
jQuery Ajax
I created a simple API with Ruby on Rails,and I'm trying to send data from a form with AngularJS. The thing is that the App is sending the post method and the backend is creating the new records, so far it's working, but it creates it with Null values.
This is the form:
<div ng-controller="postController">
<form name="messageForm" ng-submit="submitForm()">
<div class="form-group">
<label>Name</label>
<input type="text" name="content" class="form-control" ng-model="message.content">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
This is the Angular Controller:
app.controller('postController', function($scope, $http) {
// create a blank object to handle form data.
$scope.message = {};
// calling our submit function.
$scope.submitForm = function() {
$http({
method : 'POST',
url : 'http://localhost:3000/api/v1/messages',
data : $scope.message, //forms user object
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(data) {
if (data.errors) {
// Showing errors.
$scope.errorContent = data.errors.errorContent;
} else {
$scope.message = data.message;
}
});
};
});
And in the RoR's API Controller, this is the Create method:
def create
respond_with Message.create(params[:message])
end
The only rows are:
ID which is generated automatically.
And 'content'
You must assign a key to your message object in data parameter, like this:
$http({
method : 'POST',
url : 'http://localhost:3000/api/v1/messages',
data : { data: $scope.message },
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.sucess(function(data){ ... });
And then, in your controller:
def create
respond_with Message.create(params[:data])
end
Hope this help :)
I'm working on a basic reddit clone app with Rails and ember.js (via the ember-rails gem). Basically I have a 'post' model/controller in Rails which works correctly, but when I add a new post from the ember post model's create action, even if it fails the Rails validation, if I then go to the 'posts' index page which lists all the posts, I can see it there (i.e. ember is keeping the data). When I refresh it goes away, but I'm wondering what is the best way to purge that data so that it gets deleted upon rejection from the backend? Another odd thing is that simply going to the posts/new page at all creates a new blank post which is then visible on the Then on the client-side, I have the following files in app/assets/javascripts/routes:
posts_route.js:
RedditJp.PostsRoute = Ember.Route.extend({
model: function() {
return this.get('store').find('post');
}
});
posts_new_route.js:
RedditJp.PostsNewRoute = Ember.Route.extend({
model: function(){
return this.get('store').createRecord('post'); },
actions: {
create: function() {
var newPost = this.get('currentModel');
var self = this;
newPost.save().then(
function() { self.transitionTo('posts'); },
function() { }
);
}
}
});
Here's the form I'm trying to use to submit the data in posts/new.hbs:
<h1> Add a post </h1>
{{#each error in errors.title}}
<p>{{error.message}}</p>
{{/each}}
<form {{action "create" on="submit"}}>
<div>
<label>
Title<br/>
{{input type="text" value=title}}
</label>
</div>
<div>
<label>
Address<br/>
{{input type="text" value=address}}
</label>
</div>
<div>
<label>
Vote count<br/>
{{input type="text" value=voteCount}}
</label>
</div>
<button>Save</button>
</form>
and then in assets/javascripts/templates/posts/ I have index.hbs:
<h1>Posts</h1>
<ul>
{{#each}}
<li>{{title}} at {{address}} vote count: {{voteCount}}</li>
{{else}}
<li>There are no posts.</li>
{{/each}}
</ul>
and here's my router.js:
RedditJp.Router.map(function() {
this.resource('posts', function() {
this.route('new')
});
this.resource('home', function() {
});
});
RedditJp.IndexRoute = Ember.Route.extend({
redirect: function(){
this.transitionTo('home')
}
});
I was thinking I could just add a check in the posts/index.hbs file and only show records that aren't dirty, but there must be a cleaner way of doing it, so I'm wondering what would be considered best practice in this case (I'm thinking there should be some code I could add to the promise in posts_new_route.js to deal with this, but I can't quite figure it out).
Thanks a lot! And let me know if you need any additional info.
You can check if model isNew in template to hide new Record ( also you can use isEmpty property )
var record = store.createRecord('model');
record.get('isNew'); // true
record.save().then(function(model) {
model.get('isNew'); // false
});
In template will look like {{each model}}
{{#if model.get('isNew')}}
record.save().then(function(){
// Success callback
}, function() {
model..deleteRecord();
});
I am using jQuery1.4.2, ASP.NET MVC 2 and jQuery.UI-1.8.
I am creating a data input dialog which works OK when all the data is valid, but I want to validate the input data on the server and return an error to the dialog describing the error and I am not quite sure how to do that and keep the dialog open. The dialog is opened when a link is clicked. The solution may be to try to bypass more of the MVC framework's default binding that handles the submit button clicks and creates the expected ProfilePermission object and calls the Controller's AddPermission POST Action method, but I was hoping there may be an easier way without having to write more jquery/javascript code to handle the button clicks and pass the data to/from the server.
My script code looks like
$("#dialog").dialog({ modal: true,
position: ['center', 180],
width: 500,
height: 130,
autoOpen: false
});
$(".addPermissionDialog").click(function (event) {
event.preventDefault();
$("#dialog").dialog('open');
return false;
});
My View
<div id="dialog" title="Add Permission">
<%: Html.ValidationSummary("") %>
<% using (Html.BeginForm("AddPermission", "Profile"))
{ %>
<%: Html.Hidden("PersonId") %>
<%: Html.Hidden("ProfileId") %>
<div class="editor-label">
<label for="PersonName">User Name:</label>
<%: Html.TextBox("PersonName")%>
<label for="PermissionType">Permission:</label>
<select name="PermissionTypeId" id="PermissionTypeId" >
<option value="2">Edit</option>
<option value="3">View</option>
</select>
</div>
<br />
<p>
<input type="submit" name="saveButton" value="Add Permission" />
<input type="submit" id="cancelButton" name="cancelButton" value="Cancel" />
<script type="text/javascript">
document.getElementById("cancelButton").disableValidation = true;
</script>
</p>
<% } %>
</div>
<br />
<p>
<%: Html.ActionLink("Add Permission", "AddPermission", new { profileId = Model.First().ProfileId }, new { #class = "addPermissionDialog" })%>
</p>
My Controller action
[AcceptVerbs("Post")]
[HandleError]
public ActionResult AddPermission(string cancelButton, ProfilePermission profilePermission)
{
ViewData["Controller"] = controllerName;
ViewData["CurrentCategory"] = "AddPermission";
ViewData["ProfileId"] = profilePermission.ProfileId;
PermissionTypes permission = repository.GetAccessRights(profilePermission.ProfileId);
if (permission == PermissionTypes.View || permission == PermissionTypes.None)
{
ViewData["Message"] = "You do not have access rights (Edit or Owner permissions) to this profile";
return View("Error");
}
// If cancel return to previous page
if (cancelButton != null)
{
return RedirectToAction("ManagePermissions", new { profileId = profilePermission.ProfileId });
}
if (ModelState.IsValid)
{
repository.SavePermission(profilePermission);
return RedirectToAction("ManagePermissions", new { profileId = profilePermission.ProfileId });
}
// IF YOU GET HERE THERE WAS AN ERROR
return PartialView(profilePermission); // The desire is to redisplay the dialog with error message
}
LATER EDIT
I was hoping for a mechanism to return an error to the dialog using MVC's plumbing, I eventually broke down and added a save button via the jquery.ui.dialog API and handled the issue that way. I removed the buttons from the .aspx page. I returned return new EmptyResult(); from the controller's actions if everything worked OK and if there was an error
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Content(errorMessage, MediaTypeNames.Text.Plain);
// To add a button and bypass more of MVC plumbing
buttons: {
"Save": function () {
var dlg = $(this);
$.ajax({
url: "/Profile/AddPermission",
type: 'POST',
data: {
PersonId: $("#PersonId").val(),
ProfileId: $("#ProfileId").val(),
PermissionTypeId: $("#PermissionTypeId").val(),
PersonName: $("#PersonName").val()
},
success: function (data) {
dlg.dialog('close');
},
error: function (data) {
alert(data.responseText);
}
});
}
}
I was doing this kind of stuff using jquery.form and jquery dialog;
in the post action if everything is good you return Content("OK") if not you return the PartialView() (that contains the modelstate errors) after in the function that handles the successful post response you check if it is "OK" close the dialog if not you set the $("#yourDialogDiv").html(responseHtmlThatYouGotFromTheServer)
I would suggest changing the input type submit to a normal button and making an Ajax call on click of the button, to ensure that the dialog is not closed. Send data to the server using JsonValueProviderFactory from the MVC2 futures library based on Phils post. If the validation fails trap the error in the ajax error: option. If data is valid close the dialog from the Ajax complete: option. Hope this helps.