how can i get access to the form element attributes inside the function that get called on ng-submit ?
.controller('loginCtrl', function ($scope, $rootScope, $location, $window, session,$http) {
$scope.error = null;
console.log($scope);
$scope.attempt = function (url) {
//URL get passed.. but i want to fetch it from the form action attribute
var data = {username:$scope.info.u,password:$scope.info.u};
$http.post(ul, data).success(function(response) {
$scope.error = "welcome";
$rootScope.currentUser = data;
session.set('siUser', data);
$location.path('/dash');
}).error(function(reason) {
$scope.error = "failed try again" + $scope.info.p + ' ' + $scope.info.u;
});
};
})
HTML
<form role="form" ng-submit="attempt('<?=base_url('auth/login');?>')" method="post">
<fieldset>
<div class="form-group">
<input type="text" ng-model="info.u" placeholder="Username" class="form-control" ng-min-length="4" required />
<p ng-show="info.u.$invalid" class="help-block">You username is required.</p>
</div>
<div class="form-group">
<input type="password" name="password" ng-model="info.p" placeholder="Password" class="form-control" />
<p ng-show="info.p.$invalid" class="help-block">password is required.</p>
</div>
<button ng-disabled="loginForm.$invalid" class="btn btn-lg btn-success btn-block" type="submit">Login</button>
</fieldset>
</form>
currently what i'm doing is passing it to the function. but is there a cleaner way to access the element from inside controller function?
You can try something like this, in your ng-submit attribute, ng-submit="attempt('...', $event);?>')" pass the $event parameter. However don't forget to add it to your function as well, like so:
$scope.attempt = function (url, $event) {
//URL get passed.. but i want to fetch it from the form action attribute
var data = {username:$scope.info.u,password:$scope.info.u};
$http.post(ul, data).success(function(response) {
$scope.error = "welcome";
$rootScope.currentUser = data;
session.set('siUser', data);
$location.path('/dash');
}).error(function(reason) {
$scope.error = "failed try again" + $scope.info.p + ' ' + $scope.info.u;
});
};
You will be able to get your angular.element like so:
angular.element($event.target);
Let me know if this solution fits you
Related
I am trying to create simple knockout example using module pattern
var login = {}; //login namespace
//Constructor
login.UserData = function () {
var self = this;
self.UserName = ko.observable("");
self.Password = ko.observable("");
};
//View-Model
login.UserVM = function () {
this.userdata = new login.UserData(),
this.apiUrl = 'http://localhost:9090/',
this.authenticate = function () {
var data = JSON.parse(ko.toJSON(this.userdata));
var service = apiUrl + '/api/Cryptography/Encrypt';
DBconnection.fetchdata('POST', service, JSON.stringify(data.Password), response, function () { console.log('Cannot fetch data') }, null, true);
function response(res) {
console.log(res)
}
}
return {
authenticate: this.authenticate
}
}();
$(function () {
ko.applyBindings(login.UserVM); /* Apply the Knockout Bindings */
});
HTML CODE:
<form id="loginform" name="loginForm" method="POST">
<div id="form-root">
<div>
<label class="form-label">User Name:</label>
<input type="text" id="txtFirstName" name="txtFirstName" data-bind="value:login.UserData.UserName" />
</div>
<div>
<label class="form-label">Password:</label>
<input type="text" id="txtLastName" name="txtLastName" data-bind="value:login.UserData.Password" />
</div>
<div>
<input type="button" id="btnSubmit" value="Submit" data-bind="click: authenticate" />
</div>
</div>
</form>
the problem is am not able to get userdata in the viewmodel on click of submit it is returning undefined and the login object holds the changed value of textbox but on click it is returning black values.
please let me know
Also can you let me know how to implement definative module pattern in the same code.
The object you are returning from login.UserVM has only authenticate property and doesn't have userdata or apiUrl properties. So, instead using an IIFE to create an object, set login.UserVM to a constructor function similar to login.UserData. And then use new operator to create the viewModel object. Now the viewModel will have userdata and apiUrl properties (remove the return from the function)
Also, you need to change the HTML bindings to: data-bind="value:userdata.UserName". This looks for the userdata property inside the bound viewModel
var login = {}; //login namespace
//Constructor
login.UserData = function () {
var self = this;
self.UserName = ko.observable("");
self.Password = ko.observable("");
};
//View-Model
login.UserVM = function () {
this.userdata = new login.UserData(),
this.apiUrl = 'http://localhost:9090/',
this.authenticate = function () {
var data = JSON.parse(ko.toJSON(this.userdata));
console.log(data)
//var service = this.apiUrl + '/api/Cryptography/Encrypt';
//DBconnection.fetchdata('POST', service, JSON.stringify(data.Password), response, function () { console.log('Cannot fetch data') }, null, true);
function response(res) {
console.log(res)
}
}
}; // remove the () from here
ko.applyBindings(new login.UserVM()); /* Apply the Knockout Bindings */
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<form id="loginform" name="loginForm" method="POST">
<div id="form-root">
<div>
<label class="form-label">User Name:</label>
<input type="text" id="txtFirstName" name="txtFirstName" data-bind="value:userdata.UserName" />
</div>
<div>
<label class="form-label">Password:</label>
<input type="text" id="txtLastName" name="txtLastName" data-bind="value:userdata.Password" />
</div>
<div>
<input type="button" id="btnSubmit" value="Submit" data-bind="click: authenticate" />
</div>
</div>
</form>
I have this bug in my web app. So, I have a form where when I edit the form it does not update on view and server. What I want to solve is when I edit my form, I want to update the view and the server. So, here is my code below. Please, check out my code if somethings wrong. Thanks in advance. Any Help?
here is my code.
var app = angular.module("MyApp", ['ngRoute', 'ui.bootstrap']);
app.controller('MyCtrl', function($scope, $window, people) {
people.getUserInfo().then(function (response) {
$scope.userInfo = response.data;
});
$scope.inactive = true;
$scope.updateUser = function(person) {
people.updateUser(person);
};
$scope.confirmedAction = function(person) {
var index = $scope.userInfo.lawyers.map(function(e) {
return e.id;
}).indexOf(person.id);
people.confirmUser(person.id).then(function(data){ });
$scope.userInfo.lawyers.splice(index, 1);
console.log($scope.userInfo.lawyers);
$window.location.href = '#/lawyer';
};
});
});
about
<div ng-controller="MyCtrl">
<div ng-repeat="person in userInfo.lawyers | filter : {id: lawyerId}">
<a class="back" href="#/lawyer">Back</a>
<button type="button" class="edit" ng-show="inactive" ng-click="inactive = !inactive">
Edit
</button>
<button type="submit" class="submit" ng-show="!inactive" ng-click="updateUser(person)">Save</button>
<a class="delete" ng-click="confirmedAction(person);" confirm-click>Confirm</a>
<div class="people-view">
<h2 class="name">{{person.firstName}}</h2>
<h2 class="name">{{person.lastName}}</h2>
<span class="title">{{person.email}}</span>
<span class="date">{{person.website}}</span>
</div>
<div class="list-view">
<form>
<fieldset ng-disabled="inactive">
<legend>Info</legend>
<b>First Name:</b>
<input type="text" ng-model="person.firstName">
<br>
<b>Last Name:</b>
<input type="text" ng-model="person.lastName">
<br>
<b>Email:</b>
<input type="email" ng-model="person.email">
<br>
<b>Website:</b>
<input type="text" ng-model="person.website">
<br>
</fieldset>
</form>
</div>
</div>
</div>
services to my backend
app.factory('people', function ($http) {
var service = {};
service.getUserInfo = function () {
return $http.get('https://api-dev.mysite.com/admin/v1/lawyers');
};
service.confirmUser = function (lawyerId) {
return $http.put('https://api-dev.mysite.com/admin/v1/lawyers/'+lawyerId+'/confirm');
};
service.updateUser = function (person) {
return $http.put('https://api-dev.mysite.com/admin/v1/lawyers/'+ person.id, person);
};
return service;
});
HomeController
var isConfirmed = false;
app.controller('HomeController', function($scope, people) {
if (!isConfirmed) {
people.getUserInfo().then(function (response) {
$scope.userInfo = response.data;
}, function (error) {
console.log(error)
});
}
});
There are a couple of problems here.
Data from the server is not bound to the controller which means it will not display in your view.
The inputs to your form are binding to aliases and not any members of an actual scope
After you submit changes to your data, you need to get updates from your server
The inactive scope value is not updated after you save your data
which means your 'Save' button won't hide after a form is submitted.
First step is populating your $scope.userInfo in your MyCtrl controller. When you set $scope.userInfo in your HomeController only HomeController has access to $scope.userInfo and not MyCtrl.
You need to change your code such that MyCtrl sets $scope.userInfo in it's own scope so that it has access to the data like so:
app.controller('MyCtrl', function($scope, $window, people) {
// This function will now be called so that it can get the userInfo
// from the server and populate into the scope and give the controller
// access.
people.getUserInfo().then(function (response) {
$scope.userInfo = response.data;
});
// ...
});
Now you need to actually bind the input of your form to the data in your scope.
<form>
<fieldset ng-disabled="inactive">
<legend>Info</legend>
<b>First Name:</b>
<input type="text" ng-model="userInfo.lawyers[$index].firstName">
<br>
<b>Last Name:</b>
<input type="text" ng-model="userInfo.lawyers[$index].lastName">
<br>
<b>Email:</b>
<input type="email" ng-model="userInfo.lawyers[$index].email">
<br>
<b>Website:</b>
<input type="text" ng-model="userInfo.lawyers[$index].website">
<br>
</fieldset>
</form>
It's important to remember that Angular needs to bind to data in $scope before it will render changes in the DOM and using person from the person in userInfo.lawyers ng-repeat directive references an alias to a person and not to the actual data in the userInfo scope.
After you submit your changes you're going to want to update your list with new data from the server so include:
app.controller('MyCtrl', function($scope, $window, people) {
// ...
$scope.updateUser = function(person) {
people.updateUser(person)
// Now get the new data.
.then(function() {
return people.getUserInfo();
}).then(function (response) {
// Apply the new data to the scope.
$scope.userInfo = response.data;
});
};
// ...
});
Finally for the Save button issues you need to be sure that isactive value of the scope is set appropriately for when you do and don't want it to appear in the DOM. Setting the value to true hides it while setting to false reveals it. The edit button already toggles this value for you but you can also toggle this value when the function you want it to execute completes. You can do this in the updateUser function:
app.controller('MyCtrl', function($scope, $window, people) {
// ...
$scope.updateUser = function(person) {
// Hide the save button
$scope.inactive = true;
people.updateUser(person)
.then(function() {
return people.getUserInfo();
}).then(function (response) {
$scope.userInfo = response.data;
});
};
// ...
});
Additional resources for AngularJS scopes can be found here.
Im trying to create a simple login verification, however the validation function seizes to function when the validation comparison begins, and the console sais that the variable "userName is not defined" although it clearly is.
Can enyone tell me what am i defining wrong?
the angular controller code:
var app = angular.module("LoginApp", []);
app.controller("LoginController", function ($http) {
this.userName = "";
this.password = "";
this.userNameValid = true;
this.passwordValid = true;
/*submit the form*/
this.submit = function () {
alert("submit");
this.validate();
};
/* make sure user name and password has been inserted*/
this.validate = function () {
alert("validate");
var result = true;
this.userNameValid = true;
this.passwordValid = true;
if (this.userName == "") {
alert("username="+userName);
this.userNameValid = false;
result = false;
}
if (this.password == "") {
this.passwordValid = false;
result = false;
}
alert("validuserNameValid==" + userNameValid + " passwordValid==" + passwordValid);
return result;
};
});
the HTML form:
<body ng-app="LoginApp" ng-controller="LoginController as LoginController">
<form role="form" novalidate name="loginForm" ng-submit="LoginController.submit()">
<div id="loginDetails">
<div class="form-group">
<label for="user"> User Name:</label>
<input type="text" id="user" class="form-control" ng-model="LoginController.userName" required />
<span ng-show="LoginController.userNameValid==false" class="alert-danger">field is requiered</span>
</div>
<div class="form-group">
<label for="password" >Password:</label>
<input type="password" id="password" class="form-control" ng-model="LoginController.password" required />
<span ng-show="LoginController.passwordValid==false" class="alert-danger">field is requiered</span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
{{"entered information:" +"\n"+LoginController.userName+" "+ LoginController.password}}
</div>
</div>
</form>
</body>
the log:
Error: userName is not defined
this.validate#http://localhost:39191/login.js:23:13
this.submit#http://localhost:39191/login.js:11:9
anonymous/fn#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js line 231 > Function:2:292
b#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:126:19
Kc[b]</<.compile/</</e#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:274:195
uf/this.$get</m.prototype.$eval#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:145:103
uf/this.$get</m.prototype.$apply#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:145:335
Kc[b]</<.compile/</<#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:274:245
Rf#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:37:31
Qf/d#https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:36:486
Always use this judiciously. I would recommend you to store the reference of this in variable then use it wherever required.
var app = angular.module("LoginApp", []);
app.controller("LoginController", function ($http) {
//Store the reference of this in a variable
var lc = this;
//Use the stored refrence
lc.userName = "";
/* make sure user name and password has been inserted*/
lc.validate = function () {
if (lc.userName == "") {
alert("username="+userName);
lc.userNameValid = false;
result = false;
}
};
});
inside your alert boxes you have not mentioned this.userName try removing the alert boxes or change them.
I have a form with 2 input fields and requirement is that once user enters valid data into these
fields, I need to pass the input data to the factory function and get the data from server.To achieve this I thought of using $watch function but stuck at how to know if form is valid in $wathc function and then call the factory function to get data from the server.Here is the code.
Any help would be highly appreciated.
//html
<html>
<body ng-app="myModule">
<div ng-controller="myCtrl">
Product Id: <input type="text" ng-model="myModel.id" /><br/>
Product Name: <input type="text" ng-model="myModel.productname" /><br/>
</div>
</body>
</html>
//js
var myModule = angular.module('myModule',[]);
myModule.controller('myCtrl',['$scope', function($scope){
$scope.myModel = {};
var getdata = function(newVal, oldVal) {
};
$scope.$watch('myModel.id', getdata)
$scope.$watch('myModel.productname', getdata)
}]);
Wouldn't you just watch myModel, since the same function is called in both cases?
You could do this with ng-change just as easily.
<html>
<body ng-app="myModule">
<form name="productForm" ng-controller="myCtrl">
<div>
Product Id: <input type="text" name="idModel" ng-model="myModel.id" ng-change="validateID()" /><br/>
Product Name: <input type="text" ng-model="myModel.productname" ng-change="validateProduct()" /><br/>
</div>
</form>
</body>
And your JS would look like this:
var myModule = angular.module('myModule',[]);
myModule.controller('myCtrl',['$scope', 'myFactory',
function($scope, myFactory){
$scope.myModel = {};
$scope.validateID = function(){
//things that validate the data go here
if(your data is valid){
myFactory.get(yourParams).then(function(data){
//whatever you need to do with the data goes here
});
}
};
$scope.validateProduct = function(){
//things that validate the data go here
if(your data is valid){
myFactory.get(yourParams).then(function(data){
//whatever you need to do with the data goes here
});
}
};
}
]);
Using ng-change saves you from having to add a $watch to your scope (they are expensive) and will fire when the user leaves the input box. If you need to catch each keystroke, I would recommend that you use UI-Keypress and run the same functions.
To know if form is valid you have to add a form tag and inside your controller check $valid, on your example the form is always valid becaus you do not have any required field.
See the below example on codepen
The HTML
<div ng-app="myModule">
<div ng-controller="myCtrl">
<form name="myform" novalidate>
Product Id:
<input type="text" ng-model="myModel.id" />
<br/>
Product Name:
<input type="text" ng-model="myModel.productname" />
<br/>
</form>
<br/>
<div>{{result}}</div>
<div>Form is valid: {{myform.$valid}}</div>
</div>
</div>
The JS
var myModule = angular.module('myModule', []);
myModule.controller('myCtrl', ['$scope', function ($scope) {
$scope.myModel = {};
$scope.result = "(null)";
var getdata = function (newVal, oldVal) {
var valid = null;
if ($scope.myform.$valid) {
valid = "is valid";
} else {
valid = "is INVALID";
}
$scope.result = "Changed value " + newVal + " form " + valid;
};
$scope.$watch('myModel.id', getdata);
$scope.$watch('myModel.productname', getdata);
}]);
I need to work out a way of triggering NgChecked to re-evaluate it's expression after a user submits a form (which reloads the data). Ideally the trigged would be after the data has been reloaded, so the checkbox state is in line with that of the data and the amendments that have been made.
I've tried calling the expression directly after loadData() is called, however to no avail.
Do I instead need to use something like NgUpdate?
Any suggestions would be very much appreciated. Please see my code below:
view.html
<form ng-submit="updateinfo(item.downloadID); showDetails = ! showDetails;">
<input class="form-control" style="margin:5px 3px;" type="text"
ng-model="item.title" value="{{item.title}}"
placeholder="{{item.title}}"/>
<div class="checkbox" style="margin:5px 3px;">
<label for="downloadLive">
<input name="downloadLive" type="checkbox" ng-model="item.dlLive" ng-checked="liveCheckBoxState(item.dlLive);" ngTrueValue="1" ngFalseValue ="0"> Download live
</label>
</div>
<input class="btn btn-default form-control" style="margin:5px 3px;" type="submit"/>
</form>
controllers.js
// a scope function to edit a record
$scope.updateinfo = function(downloadID) {
id = downloadID
var result = $scope.items.filter(function( items ) {
return items.downloadID == id;
});
updatedata = $scope.items
$http({
method : 'PUT',
url : '/view1/downloadedit/'+id,
data : result
});
$scope.loadData();
};
//return correct state checkbox for downloadlive
$scope.liveCheckBoxState = function(dlLive) {
console.log(dlLive);
if (dlLive == 1) {
return true;
} else {
return false;
};
};
// a scope function to load the data
$scope.loadData = function () {
$http.get('/view1/downloadData').success(function (data) {
$scope.items = data;
});
};
$scope.loadData();