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
Related
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
I have created a form in a modal which allows someone to enter in plan details. I have then created the scope form in ng-model attribute as you can see below...
<form>
<div class="form-group">
<label>{{plans.title}}</label>
<input type="text" name="title" ng-model="plans.title" class="form-control" placeholder="Enter Title" required />
</div>
<div class="form-group">
<label>{{plans.overview}}</label>
<textarea name="overview" ng-model="plans.overview" class="form-control" placeholder="Overview/Purpose" required />
</div>
<div class="form-group">
<label>{{plans.notes}}</label>
<textarea name="notes" ng-model="plans.notes" class="form-control" placeholder="Plan Notes" required />
</div>
<div class="form-group">
<label>{{plans.visualplan}}</label>
<div class="button" ngf-select ng-model="plans.visualplan" name="visualplan" ngf-pattern="'image/*'" ngf-accept="'image/*'" ngf-max-size="20MB" ngf-min-height="100" >Upload Visual Plan</div>
</div>
<div class="form-group">
<button type="submit" ng-click="submit()" Value="Post">Post</button>
</div>
</form>
In my code I am then trying to pull the data from the form into my scope object for plans under title, overview, notes and visualplan. Then i have coded this to upload the data from the form into my firebase json. However upon submitting the details, the upload to json process works correctly, but it is uploading the default values for title, overview, notes and visualplan which i have initiatlly set in my dailyplans.js file. What i want to upload is the details which I have attached through ng-model instead of the initial set values. Can anyone spot what I am doing wrong?
Below is my js file.
$scope.submit = function() {
$scope.plans = {
title: 'title',
overview: 'overview',
notes: 'notes',
visualplan: 'visual plan'
}
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set($scope.plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
You are resetting the plans object when user clicks on submit. Ideally it should be outside of submit method.
This is how you should do it
$scope.plans = {
title: 'title',
overview: 'overview',
notes: 'notes',
visualplan: 'visual plan'
}
$scope.submit = function(plans) {
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set(plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
And also update the html as
<div class="form-group">
<button type="submit" ng-click="submit(plans)" Value="Post">Post</button>
</div>
Hope this helps.
Just don't overwrite your plans object:
$scope.submit = function() {
$scope.plans.title = 'title';
$scope.plans.overview = 'overview';
$scope.plans.notes = 'notes';
$scope.plans.visualplan = 'visual plan;
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set($scope.plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
This way angular can fire the listeners correctly.
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;
};
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.
I am new to angular js .I tried making a small program that consists of ajax call using angular js $http .I guess I am some where wrong ,doing some mistake.
Would be happy If someone helps out. Following is code snippet
login.html
<head></head>
<body>
<form ng-app="" ng-controller="validateCtrl" name="myForm" novalidate>
<div ng-hide="var">
<h2><center>SIGN-IN</center></h2>
<p>Username:
<br>
<input type="text" name="user" ng-model="user" required><span style="color:red" ng-show="myForm.user.$error.required" />Username is required</p>
<p>Password:
<br>
<input type="password" name="password" ng-model="password" required /> <span style="color:red" ng-show="myForm.password.$error.required">Password is required.</span>
<p>
<input type="submit" ng-click="validate()" ng-disabled=" myForm.user.$invalid ||
myForm.password.$invalid" />
</p>
</div>
<div ng-hide="welcomeVar"> <span> {{ listOfCustomers }} </span>
<h2><center>Welcome! {{ user }}</center></h2>
<button class="list" ng-click="customerList()">List of Customers</button>
<ul>
<li ng-repeat="x in listOfCustomers">{{ x.CustomerID + ', ' + x.CompanyName }}</li>
</ul>
<br>
<button class="signout" ng-click="validate()">Log Out</button>
</div>
</form>
JS part:
<script>
function validateCtrl($scope, $http) {
$scope.user = 'ABC XYZ';
$scope.password = 'abcbc';
$scope.welcomeVar = true;
$scope.
var = false;
$scope.validate = function() {
$scope.
var = !$scope.
var;
$scope.welcomeVar = !$scope.welcomeVar
};
$scope.listOfCustomers = null;
$scope.customerList = function() {
$http.get("http://www.iNorthwind.com/Service1.svc/getAllCustomers")
.success(function(data) {
$scope.listOfCustomers = data;
})
.error(function(data) {
$scope.user = 'Xyz';
});
};
}
</script>
Your code is fine, except some syntax errors, but I hope it's because you tried to remove somrthing before posting code here ;)
Also the response for your request have this structure: {GetAllCustomersResult : [//here an array of elements]} , so, in success response handler you'll have to do: $scope.listOfCustomers = data.GetAllCustomersResult ;
But it's a minor things, the main issue described here:
AngularJS performs an OPTIONS HTTP request for a cross-origin resource
To debug this, you had to open developer tools in any browser('F12' is common key to open it), and look in console and network requests.