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.
Related
I've recently started using AngularJS, and even though I am able to send data through $http when the webpage loads, I'm unable to do it when a button is pressed. My code:
<div ng-app="myApp" ng-controller="myCtrl">
Username: <input type="text" id="u" ng-model="username"><br>
Password: <input type="text" id="p" ng-model="password"><br>
Email: <input type="text" id="e" ng-model="email"><br>
First Name: <input type="text" id="fn" ng-model="firstName"><br>
Last Name: <input type="text" id="ln" ng-model="lastName"><br>
<br>
<button onclick="sendData()">Click me</button>
<br>
{{status}}
</div>
<script>
var app = angular.module('myApp', []);
var arr = new Array();
function sendData() {
arr[0] = document.getElementById("u").value;
arr[1] = document.getElementById("p").value;
arr[2] = document.getElementById("e").value;
arr[3] = document.getElementById("fn").value;
arr[4] = document.getElementById("ln").value;
app.controller('myCtrl', function($scope, $http) {
$http.post("../signup.php", {'data' : arr})
.success(function(response) {
$scope.status = response.status;
$scope.description = response.description;
$scope.content = response.content;
});
});
}
</script>
With that code, the function in app.controller doesn't execute, but if I put it outside of the sendData() function, it does execute, but right after loading the page.
Can anyone help me getting it to work when the button is pressed?
SInce you want to use angular and you use ng-model in your view you should use ng-click on your button:
<button ng-click="sendData()">Click me</button>
Even better you can use ng-submit on your form and use a submit button.
In your controller you will have something like this:
$scope.username = '';
$scope.email = '';
// better have an user object here so you will not have n variables ...
$scope.sendData = function() {
var arr = [];
arr[0] = $scope.username;
arr[1] = $scope.email;
//........
$http.post("../signup.php", {data : arr})
.success(function(response) {
$scope.status = response.status;
$scope.description = response.description;
$scope.content = response.content;
});
}
You need to define the function on the scope of your controller
HTML
<button ng-click="sendData()">Click me</button>
JS
app.controller('myCtrl', function($scope, $http) {
$scope.sendData = function(
$http.post("../signup.php", {'data' : arr})
.success(function(response) {
$scope.status = response.status;
$scope.description = response.description;
$scope.content = response.content;
});
}
});
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
I am trying to pre-populated data from backend using rest service passing id to retrieve data,this is edit mode when user click on edit process all input fields should be pre-populate associated with that id.
HTML
<input type="text" class="form-control" id="name"
ng-readonly="readOnly" ng-model="process.Name"
placeholder="Process Name" ng-maxlength="50" name="processName"
ng-required="true" data-required-msg="Process Name">
CONTROLLES.JS
$scope.editMode = false;
if ($scope.process_id != '_new' && $scope.process_id > 0) {
var process = Process.get({},{'Id': 2551});
console.log("get method")
$scope.editMode = true;
}
SERVICE.JS
App.factory('Process', function($resource) {
return $resource('app/prcs/rest/process/:id', {}, {
'query' : {
method : 'GET',
isArray : true
},
'get' : {
method : 'GET'
}
});
});
The problem is this line:
var process = Process.get({},{'Id': 2551});
you need something like this:
$scope.process = Process.get({},{'Id': 2551});
You cannot reach Controller's variables from View. You can only access those defined in $scope. Also don't forget to inject $scope into your controller.
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();