editing form in angular way - javascript

I am new to angular. I have the post list view and post edit view. my list.html. I want to edit the post on clicking the edit button but I am not having a clue on how to get the edit data. My current code looks like
list.html
<table class="table table-striped table-bordered table-hover table-full-width" id="sample_1">
<thead>
<th>Title</th>
<th>Description</th>
<th>Author</th>
<th>Action</th>
</thead>
<tbody>
<tr ng-repeat="post in blog | orderBy:'created_at':true">
<td>{{post.title}}</td>
<td>{{post.description}}</td>
<td>{{post.author}}</td>
<td>
Edit
Delete
</td>
</tr>
</tbody>
</table>
So, on clicking the button, I am navigating to my edit.html which looks like
<form role="form" class="form-horizontal" ng-submit="editPost()">
<div class="form-group">
<label class="col-sm-2 control-label" for="form-field-1">
Title
</label>
<div class="col-sm-9">
<input type="text" placeholder="Post title" id="form-field-1" class="form-control" ng-model="blog.title" value="{{blog.title}}">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="form-field-2">
Description
</label>
<div class="col-sm-9">
<textarea placeholder="description" rows="5" id="form-field-2" class="form-control" ng-model="blog.description"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="form-field-1">
Author
</label>
<div class="col-sm-9">
<input type="text" placeholder="Author" id="form-field-1" class="form-control" ng-model="blog.author">
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-2">
<button type="submit" class="btn btn-primary btn-sm">Update</button>
</div>
</div>
</form>
now I have make restful api using nodejs which I have tested using postman and its working fine. My api url are like
localhost:3000/api/posts/id
What I want to achieve now is, I want to get the data from the db on clicking the edit button.
my current js declaration
var meanApp = angular.module('meanApp', ['ui.router', 'ngMessages', 'ngResource']);
meanApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('common', {
abstract: true,
views: {
'': {
templateUrl: 'shared/common.html'
},
'header#common': {
templateUrl: 'shared/header.html'
},
'sidebar#common': {
templateUrl: 'shared/sidebar.html'
},
'script#common': {
templateUrl: 'shared/script-init.html'
},
},
})
.state('blogEdit', {
url: '/blog/edit/{id}',
parent: 'common',
views: {
'': {
templateUrl: 'components/blog/edit.html'
},
},
controller: 'postEditController'
})
});
meanApp.controller('postEditController', function(postService, $stateParams, $scope, $http, $location) {
//code to get the data from db using the id of the post
});
Any help will be appreciated.

If your trying to achieve the data from Db using nodejs.I gave my working example nodejs code (DB connectivity),
var pool = require('../config/database');
module.exports.findCampaign = function(req, res) {
//You created properties file and access or using direct query like this
//var findCampaign = select * from campaigns where campaign_sno = ?
// Accessing properties file
var findCampaign = campaignSql.get('main.findCampaign');
pool.query(findCampaign, function(err, rows) {
if (err)
throw err;
// You follow your coding standard here i did example or reference purpose i wrote like this
console.log('Data received from Db:\n');
console.log(rows);
});
};

in your config file where you are routing with ui.router....in the edit blog state:
.state('blogEdit', {
url: '/blog/edit/:id',
parent: 'common',
views: {
'': {
templateUrl: 'components/blog/edit.html'
},
},
controller: 'postEditController'
})
this :id will be treated as url parameters. now in the controller:
meanApp.controller('postEditController', function(postService, $stateParams, $scope, $http, $location) {
postService.getPostById(parseInt($stateParams.id, 10));
});
here, if your id contains character..... you may not have to parse. Now, query your Db in the service..... since you now have the parameter.....
$http({
url: 'your/path/to/server',
method: "GET",
params: {user_id: idFromServiceArgument}
});

Related

Editing data in AngularJS

I just began to study angular, tried to make some kind of SPA, but faced with problem of editing data in it. The obect is visible in console, but it hasn't appear on page, what I did wrong?
Here my controller:
var app = angular.module("testModule", ['ngRoute']);
app.config(function ($routeProvider){
$routeProvider.when('/', {
templateUrl: 'pages/main.html',
controller: 'addCtrl'
})
.when('/save', {
templateUrl: 'pages/save.html',
controller: 'editCtrl'
})
.when('/edit', {
templateUrl: 'pages/edit.html',
controller: 'addCtrl'
})
})
app.service('dataService', function($http) {
var data = {};
data.list = [];
var getData = function() {
$http.get("model/data.json").then(function (response) {
data.list = response.data;
});
}
return {
getDataFromJson: getData,
getData: data,
}
});
app.controller("mainCtrl", function($scope, dataService) {
dataService.getDataFromJson();
});
app.controller("editCtrl", function($scope, dataService) {
$scope.data = dataService.getData;
$scope.editData = function(adverse){
$scope.adverse= adverse;
console.log($scope.adverse)
}
});
and the part of page:
<div class="panel">
<form name="addForm" >
<div class="well" >
<div class="form-group">
<label for="name">Name:</label>
<input type='text' id="name" class="form-control" ng-model="adverse.name" placeholder={{adverse.name}} />
<label for="shop">Shop:</label>
<input type='text' id="shop" class="form-control" ng-model="adverse.shop" placeholder="{{adverse.shop}}" />
<label for="begin">Begin:</label>
<input id="begin" class="form-control" ng-model="adverse.begin" placeholder="{{adverse.begin}}" >
<label for="end">End:</label>
<input id="end" class="form-control" ng-model="adverse.end" placeholder="{{adverse.end}}" />
<button type="submit" class="btn btn-primary btn-block add_btn" ng-click="editData(adverse)">
Edit
</button>
</div>
</div>
</form>
</div>
Also here is a screenshot: the props of object suppose to be in the inputs but it hasn't.
enter image description here
If possible can you give me an example how I can do it by another way?
Recreated your scenario in this plunker. But it works. Please have a look at this plunker where you alo can see the StateProvider which is used instead of NgRoute
One thing I see which is incorrect is that you are sending the adverse object in the function and then setting the param to the scope adverse.
The thing is that the $scope.adverse already holds the values so you don't need to pass the value and setting it to the scope again. Remeber the scope is your glue between the view and ctrl
$scope.editData = function(){
console.log($scope.adverse)
}

Invoke Angularjs controller method from Angularjs view which related to another Angularjs controller

I am new to Angularjs, I have created simple web application that takes the details from user and display the details in the view. I am facing problem while invoking a method of one controller from another angular view. Can anyone help me, Thanks.
home.html
<div id="main">
<div id="first">
<form ng-controller="homeController as model" ng-submit="push();">
<h1>Vehicle Form</h1>
<h4>Please fill all entries.</h4>
<br>
<label>Model :</label>
<input name="dname" placeholder="Enter Model" type="text" ng-model="model.user.model">
<br>
<label>Name :</label>
<input name="demail" placeholder="Enter name" type="text" ng-model="model.user.name">
<br>
<label>Color :</label>
<input name="demail" placeholder="Enter color" type="text" ng-model="model.user.color">
<br>
<label>Price :</label>
<input name="demail" placeholder="Your Email" type="text"ng- model="model.user.price">
<br>
<input name="dsubmit" type="submit" value="Send">
</form>
</div>
</div>
<br>
<br>
<h1>Vehicle Table </h1>
<table class="table table-striped table-hover table-users" ng-controller="homeController">
<thead>
<tr>
<th>Id</th>
<th>Model</th>
<th>Name</th>
<th>Color</th>
<th>Price</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="vehicle in hello">
<td>{{vehicle.id}}</td>
<td>{{vehicle.model}}</td>
<td>{{vehicle.name}}</td>
<td>{{vehicle.color}}</td>
<td>{{vehicle.price}}</td>
<td><a class="btn mini blue-stripe" ui-sref="about" ng-click="setValue(vehicle.id)">Edit</a></td>
<td>Delete</td>
</tr>
</tbody>
</table>
home.js (controller file)
var myapp = angular.module('demo').controller("homeController", function($scope,myService){
myService.async().then(function(d){
$scope.hello=d.data;
});
var model=this;
model.user={
id:"",
model:"",
name:"",
color:"",
price:""
};
$scope.push = function(){
myService.saveUser(model.user);
model.user='';
}
});
about.html
<div id="main">
<div id="first">
<form ng-controller="aboutController" ng-submit="addValue();">
<h1>Vehicle Edit Form</h1>
<br>
<label>Id :</label>
<input name="id" placeholder="Enter Id" type="text" ng-model="id" value="value.id">
<br>
<label>Model :</label>
<input name="model" placeholder="Enter Model" type="text" ng-model="model" value="value.model">
<br>
<label>Name :</label>
<input name="name" placeholder="Enter name" type="text" ng-model="name" value="value.name">
<br>
<label>Color :</label>
<input name="color" placeholder="Enter color" type="text" ng-model="color" value="value.color">
<br>
<label>Price :</label>
<input name="price" placeholder="Your Email" type="text" ng-model="price" value="value.price">
<br>
<input name="update" type="Update" value="Send">
</form>
</div>
</div>
about.js (second controller)
angular.module('demo').controller("aboutController", function($scope, aboutService) {
$scope.value;
$scope.setValue = function() {
aboutService.getVehicle().success(function (response) {
$scope.value = studs.data;
})
};
$scope.addValue = function () {
var stud = {
id:"$scope.id",
model:"$scope.model",
name:"$scope.name",
color:"$scope.color",
price:"$scope.price"
};
aboutService.setVehicle(stud).
success( function (){
concole.log("hello");
})
};
});
rest.js(module file)
var myapp = angular
.module('demo', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'Views/home.html',
controller: 'homeController'
})
.state('about', {
url: '/about',
templateUrl: 'Views/about.html',
controller: 'aboutController'
})
.state('contact', {
url: '/contact',
templateUrl: 'Views/contact.html',
controller: 'contactController'
});
});
homeService.js
myapp.factory('myService',function($http){
var myService={
async : function(){
var promise= $http.get('http://192.168.50.127:8080/SpringRestfulVehicleDemo2/vehicle/all').then(function(response){
return response;
});
return promise;
},
saveUser : function(userArray){
$http.post('http://192.168.50.127:8080/SpringRestfulVehicleDemo2/vehicle/add ',userArray).success(
function(userArray,status,headers,config){
});
}
};
return myService;
});
aboutService.js (another service file)
myapp.factory('aboutService',function($http){
var aboutService={};
var urlBase='http://192.168.50.127:8080/SpringRestfulVehicleDemo2/vehicle/';
aboutService.getVehicle = function () {
retun $http.get(urlBase+'/byId/:id');
};
aboutService.setVehicle= function (){
return $http.post(urlBase+'/update/:id');
}
return aboutService;
});
What I am doing is getting data from server and displaying data in a table. I want to edit the selected row in another view. I facing an issue when I click edit button in home.html. It should invoke about.js (controller) setValue() method.
To do this, you need your controllers to communicate to each other. Communication can happen using any of the following methods
Use $emit + $on / $broadcast + $on
Make a service which contains that function and is injected to the controllers which want to communicate with each other.
In your case either you can move the setValue method to a shared service between the controllers using it or you can use method 1.
You already know how to make a service. For method 1 example is given below:
app.controller('One', ['$scope', '$rootScope'
function($scope) {
$rootScope.$on("CallParentMethod", function(){
$scope.parentmethod();
});
$scope.parentmethod = function() {
// task
}
}
]);
app.controller('two', ['$scope', '$rootScope'
function($scope) {
$scope.childmethod = function() {
$rootScope.$emit("CallParentMethod", {});
}
}
]);

Angular $apply does not update the view

I have a form, when I submit it, it pushes some object to my array. Beneath that form I have a table that shows all items in that array. I want my table to update automatically (without refreshing the page) when new item pushed.
Submit button:
<button type="submit" class="btn btn-default" ng-click="updateTable()">Pay</button>
In my controller:
$scope.updateTable = function() {
setTimeout(function () {
$scope.$apply();
$scope.$digest();
}, 0);
};
However, it does not work.
I tried different approaches like $watch service, but i`ve got the same result.
Table
<div class="row paytable">
<div class="col-xs-10 col-xs-offset-1">
{{payments.length}}
<table class="table table-hover ">
<tr>
<td>Id</td>
<td>Amount</td>
<td>Cause</td>
</tr>
<tr ng-repeat="item in payments">
<td>{{item.id}}</td>
<td>{{item.amount}}</td>
<td>{{item.cause}}</td>
</tr>
</table>
</div>
</div>
Controller
app.controller('mainController', [ 'user', '$rootScope', '$scope', 'payment', '$timeout', function(user, $rootScope, $scope, payment, $timeout) {
user.getUsers();
user.newUser();
$rootScope.currentUser = user.currentUser();
$scope.payments = payment.getPayments();
$scope.newPayment = payment.newPayment;
$scope.updateTable = function() {
setTimeout(function () {
console.log('apply ------------');
$scope.$apply();
$scope.$digest();
}, 0);
};
$scope.showPayMessage = function() {
console.log('im here');
$scope.showSM = true;
$timeout(function() {
$scope.showSM = false;
}, 2000);
};
}]);
payment - my service for array manipulation.
Form
<div class="newpay row" >
<div class=" col-xs-10 col-xs-offset-1">
<h1>Hello, {{currentUser.name}}</h1>
<h4 ng-show="showSM" class="bg-success">Payment confirmed</h4>
<form name="inputform" ng-submit="newPayment(amount, cause); showPayMessage();">
<div class="form-group">
<label for="exampleInputEmail1">Amount</label>
<input type="number" name="amount" ng-model="amount" class="form-control" id="exampleInputEmail1" placeholder="Amount" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Cause</label>
<input type="text" name="cause" ng-model="cause" class="form-control" id="exampleInputPassword1" placeholder="Cause" required>
</div>
<button type="submit" class="btn btn-default" ng-click="updateTable()">Pay</button>
</form>
</div>
</div>
payments: {{payments.length}}
<payments-table payments="payments"></payments-table>
To display that table I created directive.
$scope.$apply and $scope.$digest are better suited for working with 3rd party libraries or testing. In your case Angular is well aware to your changes. The thing is, your payments array, that resides in a service should be queried again after submitting a new item (unless you have a direct reference to the array, then no query should be made).
Like this:
View
<form name="inputform" ng-submit="onSubmit()">
Controller
$scope.onSubmit = function() {
newPayment($scope.newItemAmount, $scope.newItemCause); // Assuming they are properties in the controller
showPayMessage();
$scope.payments = payment.getPayments(); // getting the updated array
}

AngularJS: pass perameter to $location.path

I suspect what I'm trying to do is very simple, I'm new to Angular so some obvious practices sort of go over my head. I'm having trouble accessing the show view (sorry, I'm coming to angular from Rails, so I still think in those terms a little bit) for my Acts resource. The view renders fine, but it isn't displaying the data I would like. I suspect the template isn't receiving the $scope.act variable I'm defining in the controller. When I use console.log in the controller, I can see that the variable contains all the data I want to use. I assume I have to do something to pass the variable as a parameter to the template, but I'm not sure how I'd do that.
Here's my code:
app.js
$(document).on('page:load', function() {
return $('[ng-app]').each(function() {
var module;
module = $(this).attr('ng-app');
return angular.bootstrap(this, [module]);
});
});
var snowball_effect = angular.module('snowball_effect', [
'templates',
'ngRoute',
'ngResource',
'controllers'
]);
snowball_effect.config([
'$routeProvider', function($routeProvider) {
return $routeProvider
.when('/', {
templateUrl: "static_pages/templates/index.html",
controller: 'StaticPagesController'
})
.when('/acts/index', {
templateUrl: "acts/templates/index.html",
controller: 'ActsController'
})
.when('/acts/:id', {
templateUrl: "acts/templates/show.html",
controller: 'ActsController'
});
}
]);
var controllers = angular.module('controllers', []);
ActsController.js
controllers = angular.module('controllers');
controllers.controller('ActsController', [
'$scope',
'$routeParams',
'$location',
'$resource',
function($scope,$routeParams,$location,$resource) {
var Act = $resource('/acts/:actId', {
actId: "#id",
format: 'json'
}, {
'create': {
method: 'POST'
}
});
$scope.acts = Act.query();
$scope.addAct = function() {
act = Act.save($scope.newAct, function() {
$scope.acts.push(act);
$scope.newAct = '';
});
}
$scope.deleteAct = function(act) {
Act.delete(act);
$scope.acts.splice($scope.acts.indexOf(act), 1);
}
$scope.linkToShowAct = function(act) {
$scope.act = act;
console.log($scope.act);
$location.path('acts/' + act.id);
}
}]);
show.html
<div class="acts-show">
<div class="container" ng-controller="ActsController">
<div class="body">
<h1>
{{act.name}}
</h1>
<p class="act-show-description">
{{act.description}}
</p>
<p class="act-show-inspires">
<strong>Inspires:</strong>
{{act.inspires}}
</p>
Edit
Back
</div>
</div>
</div>
index.html
<div class="actions_body">
<div class="container">
<h2>Listing Actions</h2>
<div ng-controller="ActsController" class="body">
<table class="row">
<thead>
<tr>
<th class="col-md-2 col-md-offset-1 active">
<label>Name</label>
</th>
<th class="col-md-4">Description</th>
<th class="col-md-2">Inspires</th>
<th colspan="2" class="col-md-2">Modify</th>
</tr>
</thead>
<tbody ng-repeat="act in acts">
<td class="col-md-offset-1 col-md-2">{{act.name}}</td>
<td class="col-md-4">{{act.description}}</td>
<td class="col-md-2">{{act.inspires}}</td>
<td>Edit</td>
<td><button ng-click="deleteAct(act)">Delete</a></button>
</tbody>
</table>
<br>
<button ng-click="newActShow=true">New Action</button>
<button ng-click="newActShow=false">Hide</button>
<div ng-show="newActShow" id="newAct">
<div class="row">
<form class="form-inline" ng-submit="addAct()">
<div class="col-md-3 form-group">
<label for="newActname">Name</label>
<input type="text" ng-model="newAct.name" id="newActname" placeholder="Name" class="form-control col-md-2">
</div>
<div class="col-md-3 form-group">
<label for="newActdescription">Description</label>
<input type="textarea" ng-model="newAct.description" id="newActdescription" placeholder="Description" class="form-control col-md-2">
</div>
<div class="col-md-3 form-group">
<label for="newActinspires">Inspires</label>
<input type="number" ng-model="newAct.inspires" id="newActinspires" placeholder="Inspires" class="form-control col-md-2">
</div>
<div class="col-md-3 form-group">
<input type="submit" value="+" class="btn btn-success">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
try $locationChangeStart in order to make sure your value is set to the scope variable before the state actually changes and the route happens, even if you put the $location.path('acts/' + act.id); before setting the variable, there is no guarantee that the value will be set before the state change (the actual routing).
I would prefer (a more safe value setting method) using a promise for example ..

Angular nested state has to use $scope.parent from same controller, why?

I have a table, which loops over a scope called $scope.sites.
I'm submitting a form which saves a new site to a DB, and then adds to the site scope.
However, when I update $scope.sites, it doesn't update the table. The table is under the same SiteCtrl controller.
The scope is definitely being appended to, as if I output {{ sites.length }} after the form has posted, its value increases (and the data appears in the DB).
If I add {{ sites.length }} to the same part that the form is included (in the ui-view) it updates, outside of that and it doesn't.
Here's some of the code:
The Javascript
Note, I'm using ui-router for nested states.
myApp.config(function($stateProvider, $urlRouterProvider){
// The default route
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'app/partials/welcome.html',
controller: 'WelcomeCtrl'
})
.state('entity', {
url: '/entity/:id',
params: { id: "" },
templateUrl: 'app/partials/entity/index.html',
controller: 'EntityCtrl'
})
.state('entity.site', {
url: '/site',
templateUrl: 'app/partials/site/index.html',
controller: 'SiteCtrl'
})
.state('entity.site.create', {
url: '/create',
templateUrl: 'app/partials/site/create.html',
controller: 'SiteCtrl'
})
....
myApp.controller('SiteCtrl', ['$scope', '$http', '$stateParams', function($scope, $http, $stateParams) {
$scope.entity_id = $stateParams.id;
$scope.site_uuid = $stateParams.siteuuid;
$scope.sites = {};
$scope.site = {};
$scope.errors = {};
$scope.result = {};
$scope.formData = {};
$http({ method: 'GET', url: 'siteurl' }).
success(function (data, status, headers, config) {
$scope.sites= data.data;
}).
error(function (data, status, headers, config) {
console.log(data.result);
console.log(data.code);
});
$scope.submitForm = function() {
$http.post('submiturl', $scope.formData).success(function(data) {
//Clear the form
$scope.formData = {};
$scope.site = data.data;
$scope.sites.push($scope.site);
}).error(function(data){
$scope.errors = data;
});
}
}]);
The HTML
<div ng-controller="SiteCtrl">
<h1>Sites <a ui-sref="entity.site.create" class="btn"><i class="fa fa-plus"></i> Add New Site</a></h1>
<ui-view></ui-view> <!---- The form is included here by a ui-router state --->
<pre>{{ sites.length }}</pre> <!-- this doesnt update, nor does the table --->
<div class="form-group">
<label for="filter">Filter</label>
<input ng-model="filter" class="form-control">
</div>
<table class="striped">
<thead>
<tr>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="site in sites | filter:filter">
<td><a ui-sref="entity.site.show({siteuuid:site.uuid})" ui-sref-active="child-active">{{ site.name }}</a></td>
</tr>
</tbody>
</table>
The Form
<h1>Create a New Site at {{ entity.name }} <a ui-sref="entity.site" class="btn">Close</a></h1></h1>
<pre>{{ result }}</pre>
<pre>{{ errors }}</pre>
<pre>{{ site }}</pre>
<pre>{{ sites.length }}</pre> <!---- This updates --->
<form name="createNewSiteForm" method="post" ng-submit="submitForm()">
<div class="form-group">
<label for="name">Site Name</label>
<input type="text" name="name" class="form-control" ng-model="formData.name" autocomplete="off" required />
{{ errors.name }}
</div>
<div class="form-group">
<input type="submit" name="create" value="Save {{ formData.name }}" />
</div>
</form>
The form is included as a nested view in the
If there's anything else you'd like to see let me know and I can post it up.
Update
So the solution was to use:
$scope.parent.sites.push($scope.site);
My question is, do I have to use the parent, when the scope should be inherited due to being in the same Controller?
I'm new to Angular shedding some light on this would be very useful for my learning.

Categories