create data driven angular form - angularjs

I have a project that needs to create a form with the title of each text field comes from a json from another server.
I need to use ng-repeat to show the title and use ng-model for the text field itself, but how do I return all the result back to the server in a json format?
Here is my html part
<div class="row" ng-controller="createworkshopController">
<form role="form" ng-submit="submitWorkshop()">
<div>
<div ng-repeat="x in form">
<h4>{{x.field_name}}</h4>
<input class="form-control" placeholder="{{x.field_name}}" ng-model="result.form[field_name]">
</div>
</div>
<hr>
<div align="right">
<button type="submit" class="btn btn-default" ng-click="submitWorkshop()">Submit</button>
<button type="reset" class="btn btn-default">Reset</button>
</div>
</form>
</div>
And here is what I have for angular controller
app.controller('createworkshopController', function($scope, $http) {
$http.get(end_url + ':' + port + '/createworkshop')
.success(function(data) {
$scope.form = data.Workshop;
});
$scope.submitWorkshop = function() {
};
});
Here is a picture of what the html look like right now, The form title is passed in easily.
Please help me! I'm still learning! Thanks!!!

$http({ method: 'POST', data: $scope.result.form, url: 'path/to/api' })
This will send JSON data of the $scope.result.form object to the required API URL.

Related

AngularJS 1.x: Dynamically created multiple File Upload fields

You have to excuse me, I do not use Angular that often. I need to implement a solution in which I can upload files from dynamically generated input fields.
The catch is that I cannot use any directives (this is due to the framework I am using in which AngularJS is implemented).
My current code for creating fields:
$scope.addNewFile = function() {
var newFileNo = $scope.files.length + 1;
$scope.files.push({'id': 'file' + newFileNo});
};
$scope.removeFile = function() {
var lastFile = $scope.files.length - 1;
$scope.files.splice(lastFile);
};
And here is the code for uploading files (not correct, because of static id and name values:
$scope.uploadFile = function() {
var file = document.getElementById('file').files[0],
r = new FileReader;
r.onloadend = function (e) {
var data = e.target.result;
console.log('data');
console.log(data);
// http.post
};
r.readAsArrayBuffer(file);
};
And here is my HTML:
<div data-ng-repeat="file in files">
<div class="row top-buffer">
<div class="col-lg-10">
<input type="file"
ng-model="file.name"
name="file"
class="form-control"
id="file">
</div>
<div class="col-lg-2 text-right">
<div class="btn btn-primary" ng-click="uploadFile()">Upload</div>
</div>
</div>
</div>
<div class="row top-buffer">
<div class="col-lg-11"></div>
<div class="col-lg-1 text-right">
<div class="glyphicon glyphicon-plus" aria-hidden="true" ng-click="addNewFile()"></div>
<div class="glyphicon glyphicon-minus" aria-hidden="true" ng-click="removeFile()"></div>
</div>
</div>
I can't really understand how I can get the values of dynamically generated file fields... any help appreciated!
There is no ng-model for <input type=file, but you can achieve what you want setting the id dynamically with ng-attr:
<div ng-repeat="file in files">
{{file.id}}:
<input type="file"
ng-attr-name="{{file.id}}"
ng-attr-id="{{file.id}}">
</div>
On uploadFile() you can post them:
$scope.uploadFile = function() {
$scope.files.forEach(function(file) {
// $http.post: document.getElementById(file.id).files[0])
});
};
Example on Fiddle: https://jsfiddle.net/virgilioafonsojr/92nw4j4f/1/
I hope it helps.
Writing an uploader properly is a very difficult task. A major problem with an upload component/directive is getting it to work in Internet Explorer; because it can only be used once in IE. Another problem is that IE will not let you programmatically "press" the button, it must be a real mouse click.
There are upload libraries out there for AngularJs, just google. However if you are intent on doing it yourself then you can use my git repo as an example of how it should be done. Just use the jwtUploader and jwtUploaderButton directives.
https://github.com/smylydon/SEPE-7WCM0033-0206-FRONTEND/tree/master/client/app

Angular Two-Way data-binding not refreshing ng-repeat on $scope change

My functionality is very simple, and I have to imagine very common. I have a page that lists a collection of 'age groups', and provides functionality to add an 'age group'. I simply would like to have the page immediately reflect the change when a new 'age group' is added.
In early versions, I had simply used the $rootScope in my service to put all 'age groups' in the $rootScope when the $http request was completed. On this latest refactoring I am removing all use of $rootScope in my app, and it is becoming problematic.
The code for the HTML view is as follows: [NOTE: all code considered extraneous has been removed from all code snippets]
<div id="tabContent" class="tab-pane fade in active" ng-show="subIsSelected(1)">
<div class="row">
<div class="col-xs-12">
<form class="form-inline">
<button type="button" class="btn btn-success" ng-click="openAddAgeGroup()">Add Age Group</button>
</form>
</div>
</div>
<hr />
<div class="row row-content">
<div class="col-xs-12">
<h4 ng-show="!areAgeGroups()">No current age groups.</h4>
<ul class="media-list" ng-show="areAgeGroups()">
<li class="media" ng-repeat="ageGroup in ageGroups" style="padding:10px; background: lightGray;">
<div class="media-left media-top" >
<img class="media-object img-thumbnail" style="width: 75px;" ng-src="./images/trfc.png" alt="club logo">
</div>
<div class="media-body">
<h3 class="media-heading" style="padding-top: 20px;">{{ageGroup.name}}</h3>
<button type="button" class="btn btn-xs btn-primary" style="width: 50px;" ng-click="openEditAgeGroup(ageGroup)">Edit</button>
<button type="button" class="btn btn-xs btn-danger" style="width: 50px;" ng-click="deleteAgeGroup(ageGroup)">Delete</button>
</div>
</li>
</ul>
</div>
</div>
</div>
when first loaded, the page correctly shows all 'age groups' that are in the $scope.ageGroups array.
On clicking the button to add an 'age group', an ng-dialog is created as follows:
$scope.openAddAgeGroup = function() {
console.log("\n\nOpening dialog to add age group");
ngDialog.open({ template: 'views/addAgeGroup.html', scope: $scope, className: 'ngdialog-theme-default', controller:"HomeController" });
};
and that dialog is populated as such:
<div class="ngdialog-message">
<div class="">
<h3>Add a New Age Group</h3>
</div>
<div> </div>
<div>
<form ng-submit="addAgeGroup()">
<div class="form-group">
<label class="sr-only" for="name">Age Group Display Name</label>
<input type="text" class="form-control" id="name" placeholder="age group name" ng-model="ageGroupForm.name">
</div>
<div class="form-group">
<label class="sr-only" for="birthyear">Birth Year</label>
<input type="text" class="form-control" id="birthyear" placeholder="birth year" ng-model="ageGroupForm.birthyear">
</div>
<div class="form-group">
<label class="sr-only" for="socceryear">Soccer Year</label>
<div class="input-group">
<div class="input-group-addon">U</div>
<input type="text" class="form-control" id="socceryear" placeholder="soccer year" ng-model="ageGroupForm.socceryear">
</div>
</div>
<button type="submit" class="btn btn-info">Add</button>
<button type="button" class="btn btn-default" ng-click=closeThisDialog("Cancel")>Cancel</button>
</form>
</div>
</div>
When the form is submitted, the 'age group' is added to the database, from the controller:
'use strict';
angular.module('ma-app')
.controller('HomeController', ['$scope', 'ngDialog', '$state', 'authService', 'coreDataService', 'userService', '$rootScope', 'clubService', 'schedulingService', function($scope, ngDialog, $state, authService, coreDataService, userService, $rootScope, clubService, schedulingService) {
...
$scope.addAgeGroup = function() {
coreDataService.addAgeGroup($scope.ageGroupForm)
.then(function(response) {
coreDataService.refreshAgeGroups()
.then(function(response) {
coreDataService.setAgeGroups(response.data);
$scope.ageGroups = coreDataService.getAgeGroups();
console.log("\n\n\nretrieved age groups and put them in scope");
console.log($scope.ageGroups);
ngDialog.close();
});
}, function(errResponse) {
console.log("Failed on attempt to add age group:");
console.log(errResponse);
});
};
The coreDataService is defined as follows:
'use strict';
angular.module('ma-app')
.service('coreDataService', ['$http', 'baseURL', 'googleGeolocateBaseURL', 'googleGeocodeKey', 'googleMapsBaseURL', function($http, baseURL, googleGeolocateBaseURL, googleGeocodeKey, googleMapsBaseURL) {
var ageGroups = {};
var ageGroupsLoaded = false;
this.getAgeGroups = function() {
return ageGroups;
};
this.setAgeGroups = function(newAgeGroups) {
ageGroups = newAgeGroups;
ageGroupsLoaded = true;
};
this.addAgeGroup = function(formData) {
//post age group:
var postString = '{ "birth_year": "' + formData.birthyear + '", "soccer_year": "U' + formData.socceryear + '", "name": "' + formData.name + '" }';
console.log("Posting age group with string: " + postString);
return $http({
url: baseURL + 'age_groups/',
method: 'POST',
headers: {
'content-type': 'application/json'
},
data: postString
});
};
}]);
So, when an 'age group' is added, console logging indicates that the new 'age group' is in the collection now stored in the $scope.ageGroups array, but the HTML's ng-repeat does not reflect the new 'age group'. Only when I navigate to another tab in the interface, and then return to the tab containing the 'age groups' is the newly added 'age group' displayed.
Updated:
After you update your value you need to tell angular that its been updated. If you wrap your code in a $timeout. On the next digest cycle the view will get updated. See here for more information.
...
$timeout(function() {
$scope.ageGroups = coreDataService.getAgeGroups();
// anything you want can go here and will safely be run on the next digest.
})
...
The $timeout basically runs on the next $digest cycle thus updating your value in the view.
I would suggest wrapping your ng-repeat part in a directive, fire an event on add method and listen to it from the directive:
this.addAgeGroup = function(formData) {
// do stuff
$scope.$broadcast('itemadded');
}
Inside your directive link function:
$scope.$on('itemadded', function() {
$scope.ageGroups = coreDataService.getAgeGroups();
});
I would recommend using the ControllerAs syntax which will refresh the ng-repeat, if the array to which it is bound to gets updated.
Refer the answer given here - ng-repeat not updating on update of array

How to add text box runtime and insert its value to db in angularjs

I want to create Curd app using AngularJS & MVC.
In that I am able to add, update and delete particular data from grid, but there is one task where I am getting stuck.
Here what I need to do is, I should be able to add multiple run time text box on that insert page to take any no of input from user, so I don't know how to do it and how to add those run time added text box values in DB.
It would be much appreciated if you help me on this.
Try this,
Here is the working fiddle
<div ng-controller="MyCtrl">
<div class="row" ng-repeat="(key,val) in data">
<div class="col-md-12">
<input type="text" ng-model="val.text">
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-primary" ng-click="addTextbox()">
Add Textbox
</button>
</div>
<div class="col-md-12">
<button class="btn btn-success" ng-click="sendDataToServer()">
Send Data
</button>
</div>
</div>
<div class="row">
<div class="col-md-12">
Result = {{data}}
</div>
</div>
</div>
Controller's code
var myApp = angular.module('myApp',[]);
function MyCtrl($scope,$http) {
$scope.data = [];
$scope.addTextbox = function(){
$scope.data.push({'text':''});
}
$scope.sendDataToServer = function(){
console.log(JSON.stringify($scope.data));
$http({
url: 'your_server_url',
method: "POST",
data: JSON.stringify($scope.data),
headers: {
'Content-Type': undefined
}
}).then(function(res) {
// do stuff on success
}, function(errorMsg) {
console.log(errorMsg);
// showing error
});
}
}
Here you will get all textbox's data into $scope.data, Now you can send this data by clicking Send Data button.
Provide the url where you want to submit this data.
Comment if you have any issue.

Trouble getting Comment Form to POST - Angular App

I'm relatively new to Angular. I'm trying to get my comment form of this blog app to post comments and not just keep them in Javascript but via API POST to my database and store them there. I'm able to GET comments as well as other blog post information but for whatever reason I can't POST.
BlogService.js
angular.module('BlogService', [])
.factory('BlogService', ['$http', function($http) {
return {
// Call to GET Blog API
get : function() {
return $http.get('/api/blog');
},
// Call to GET Blog API via ID
show : function() {
return $http.get('/api/blog/' + id);
},
// Call to POST new data using Blog API
create : function(blogData) {
return $http.post('/api/blog', $scope.formData);
},
// Call to POST Comments in Blog API
createComment : function(commentData) {
return $http ({
method: 'POST',
url: '/api/blog/' + id + '/comments',
header: { 'content-type' : 'application/x-www-form-urlencode},
data: $.param(commentData)
});
},
// Call to PUT to update data using Blog API
update : function(id) {
return $http.put('/api/blog' + id);
},
// Call to DELETE data using Blog API
delete : function(id) {
return $http.delete('/api/blog/' + id);
}
}
}]);
CommentCtrl
To note, this CommentCtrl is a part of a larger BlogCtrl.js. I just separated it into its own controller. If it'll help, I can post the whole file.
...
.controller('CommentCtrl', ['$scope', '$http', 'BlogService', function($scope, $http, BlogService) {
this.commentData = {};
this.addComment = function(post) {
BlogService.createComment(this.commentData)
.success(function(data) {
this.commentData = {};
this.commentData.createdOn = Date.now();
post.comments.push(this.commentData);
this.commentData = {};
})
.error(function(data) {
console.log('Error: ' + data);
});
};
}]);
blog.html
The form is the part that I'm trying to POST. This is just a snippet of the markdown. Let me know if you would like to see the whole html file.
<div class="post" ng-repeat="post in blog.posts" ng-show="blog.isSelected($index)">
<div>
<h2>{{post.title}}</h2>
<img ng-src="{{post.image}}" ng-show="{{post.image}}"/>
<cite>by {{post.author}} on {{ post.createdOn | date:'medium' }}</cite>
<div class="post-body">
<p>{{post.body}}</p>
</div>
<div ng-controller="CommentCtrl as CmtCtrl">
<button class="icon-button" ng-click="post.likes = post.likes+1">
<i class="fa fa-thumbs-up"></i> {{post.likes}}
</button>
<button class="icon-button" ng-click="post.dislikes = post.dislikes+1">
<i class="fa fa-thumbs-down"></i> {{post.dislikes}}
</button>
<h3> Comments <h3>
<form class="form-style" name="commentForm" ng-submit="commentForm.$valid && CmtCtrl.addComment(post)" novalidate>
<h4> Add Comment: </h4>
<div>
<input type="text" class="comment-form form-control input-lg" name="body" ng-model="commentData.body" required placeholder="Please Leave Your Comment Here!"/>
</div>
<h4> Name: </h4>
<div>
<input type="text" class="comment-form form-control input-sm" name="author" ng-model="commentData.author" required placeholder="Name"/>
</div>
<div>
<button type="submit" class="btn comment-button button-style intro-social-buttons">Submit</button>
</div>
<!--<textarea class="comment-form" ng-model="CmtCtrl.comment.body" cols="30" rows="6" required></textarea></br>
<label for=""> <h4>Name:</h4> </label></br>
<input class="comment-form" type="text" ng-model="CmtCtrl.comment.author" required placeholder="Name"/></br>
<input class="btn comment-button button-style intro-social-buttons" type="submit" value="Submit"></br>-->
</form>
<ul>
<li ng-repeat="comment in post.comments">
"{{comment.body}}"
<cite>- <b>{{comment.author}}</b></cite>
</li>
</ul>
</div>
</div>
</div>
Also, to note that I use Mongoose and my schema allows body, author and date. I made it a nested array within my blog database as I wanted it to be attached to the individual blog post.
Let me know if there is anything else I can answer or give any other files.
Thanks

PUT request in Angular not sending updated data within XHR Header

I am a beginner and new to AngularJS. I am trying to build an Edit/Update function.
The edit function doesn't do much, it just copies the model data to the Form inputs:
// Edit post
$scope.editPost = function(post){
$scope.title = post.title;
$scope.link = post.link;
};
The Update function should (after clicking the Update Button) take the edited data of the inputs, to update the post model:
// Update post
$scope.updatePost = function(post){
posts.update(post, {
title: $scope.title,
link: $scope.link
}).success(function() {
ToastService.show('Post updated');
});
};
The Edit Part works, when I edit the title input and click the Submit Button of the Edit Form, it sends a PUT request, but it seems to doesn't send the updated data within the PUT - it just sends a request with the original data.
The posts.js service:
angular.module('bidrp')
.factory('posts', [
'$http',
function($http){
var o = {
posts: [{title:"hey", upvotes:123}]
};
o.update = function(post) {
return $http.put('/posts/' + post.id, post).success(function(data){
o.posts.push(data);
});
};
Template where Post is displayed and editPost is triggered:
<div ng-repeat="post in posts | orderBy: '-upvotes'">
<md-button class="md-icon-button md-accent" aria-label="Vote-Up" ng-click="incrementUpvotes(post)">
<i class="material-icons">thumb_up</i>
</md-button>
{{post.upvotes}}
<span style="font-size:20px; margin-left:10px;">
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</span>
<span>
posted by <a ng-href="#/users/{{post.user.username}}">{{post.user.username}}</a>
</span>
<span>
Comments
Edit
Delete
</span><br>
<div ng-show="showEditForm" ng-include="'home/_edit-post.html'"></div>
</div>
<div ng-include="'home/_add-post.html'"></div>
_edit-post.html partial:
<form ng-submit="updatePost(post)">
<h3>Edit post</h3>
<div ng-include="'home/_form-post.html'"></div>
</form>
_form-post.html partial:
<md-input-container>
<label>Title</label>
<input required type="text" ng-model="title">
</md-input-container>
<md-input-container>
<label>Link</label>
<input type="text" ng-model="link">
</md-input-container>
<md-button type="submit" class="md-raised md-primary">Submit</md-button>
What am I doing wrong, how can I send the edited form data within the PUT request?
This is happening because, your, are just passing the original post object generated by ngRepeat to the update function not the $scope.post. When using ng-model="post" this will be attached to the $scope object.
You do not need the editPost function, the new data are already passed to $scope.title/$scope.title by ngModel directive (doing this will re-update the $scope.tile, $scope.link with the old values):
// Edit post
$scope.editPost = function(post){
$scope.title = post.title;
$scope.link = post.link;
};

Resources