i have developed a comment system using Angular JS. Unfortunately if a user inserts a link in his comment, the link is not clickable in the displayed comment.
How can i achieve this ?
Here is my HTML code:
<section class="comment-list" ng-hide="loading" ng-repeat="comment in comments">
<article class="row">
<div class="col-md-2 col-sm-2 hidden-xs">
<figure class="thumbnail">
<img class="img-responsive" src="#{{ comment.user.avatar }}" />
</figure>
</div>
<div class="col-md-10 col-sm-10" style="padding-bottom: 10px;">
<div class="comment_panel panel-default arrow left">
<div class="panel-body">
<header class="text-left">
<div class="comment-user"><i class="fa fa-user"></i> #{{ comment.user.name }}</div>
<time class="comment-date"><i class="fa fa-clock-o"></i> #{{ comment.date }}</time>
</header>
<div class="comment-post">
<p ng-bind-html="sanitizedComment"></p>
</div>
</div>
</div>
</div>
</article>
The comment body is inside the #{{ comment.comment.content }}
Here is the angular controller:
angular.module('mainCtrl', [])
// inject the Comment service into our controller
.controller('mainController', function($scope, $http, $sce, Comment) {
// object to hold all the data for the new comment form
$scope.commentData = {};
$scope.sanitizedComment = $sce.trustAsHtml($scope.comment.comment.content);
// loading variable to show the spinning loading icon
$scope.loading = true;
// get all the comments first and bind it to the $scope.comments object
// use the function we created in our service
// GET ALL COMMENTS ==============
Comment.get()
.success(function(data) {
$scope.comments = data;
$scope.loading = false;
});
// function to handle submitting the form
// SAVE A COMMENT ================
$scope.submitComment = function() {
$scope.loading = true;
// save the comment. pass in comment data from the form
// use the function we created in our service
Comment.save($scope.commentData)
.success(function(data) {
// if successful, we'll need to refresh the comment list
Comment.get()
.success(function(getData) {
$scope.comments = getData;
$scope.loading = false;
});
})
.error(function(data) {
console.log(data);
});
};
// function to handle deleting a comment
// DELETE A COMMENT ====================================================
$scope.deleteComment = function(id) {
$scope.loading = true;
// use the function we created in our service
Comment.destroy(id)
.success(function(data) {
// if successful, we'll need to refresh the comment list
Comment.get()
.success(function(getData) {
$scope.comments = getData;
$scope.loading = false;
});
});
};
});
<div class="comment-post>
<p ng-bind-html="comment.comment.content"></p>
</div>
Should do the trick.
Related
I have an angular app that consists of a three tabbed form. Each tab is using its own controller and designated service.
When the submit button is pressed on the form, the function found in MainCtrl entitled $scope.postis suppose to post all form field data that was retrieved from each form fields ng-model.
On the server side, I receive the posted object that is formed in the Main Controller. This POST contains all the values for each object property except for work. I receive an empty object as a value for the work property.
Why am I unable to retrieve the work.comments ng-model found in the code for my template? Even when console loggin, I am unable to retrieve this item.
This is my first go at an Angular app and I am really trying to learn how to do things properly. If you happen to notice something inherently stupid, please do let me know.
Controller:
.controller('WorkCtrl', function ($scope, $ionicModal, TaskService, WorkService) {
$scope.work = {};
WorkService.add($scope.work);
});
Service:
.factory('WorkService', function() {
var work = {};
return {
add: function(data) {
work['work'] = data;
//work = data;
},
list: function() {
return work;
}
};
})
Template:
<div class="list" ng-controller="WorkCtrl">
<label class="item item-input item-floating-label">
<button class="button button-clear item-icon-right" ng-click="newTask()">New Task<i class="icon ion-ios-plus-outline"></i></button>
</label>
<label class="item item-input item-floating-label">
<span class="input-label">Comments</span>
<textarea placeholder="Comments" rows="6" ng-model="work.comments"></textarea>
</label>{{work | json}}
</div>
<div ng-controller="TaskCtrl">
<div ng-show="ifTasks()">
<div class="row header">
<div class="col tableRow">Task</div>
<div class="col tableRow">Edit</div>
<div class="col tableRow">Remove</div>
</div>
<div class="row" ng-repeat="task in tasks track by task.id">
<div class="col tableRow">{{task.choice}}</div>
<div class="col tableRow" ng-controller="WorkCtrl"><button class="button button-small button-balanced" ng-click="editTask({{task.id}})">Edit</button></div>
<div class="col tableRow"><button class="button button-small button-assertive" ng-click="del({{task.id}})">Delete</button></div>
</div>
</div>
</div>
Main Controller:
.controller('MainCtrl', function($scope, $http, SiteService, TaskService, WorkService, LabourService) {
$scope.toFetch = [];
var obj = {
site: SiteService.list(),
tasks: TaskService.list(),
work: WorkService.list(),
labour: LabourService.list()
};
$scope.post = function() {
console.log(obj);
$http({
url: 'http://localhost:1818/send/report',
method: 'POST',
data: obj,
headers: {'Content-Type': 'application/json'}
})
.then(function(data) {
console.log(data);
});
};
});
I need to fetch data from my database, updated a div and onclick update another div.
I managed to fetch the data but I fail to load additional by onCLick.
My Code:
var app = angular.module('mainApp', [], function($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
app.controller('mainController', function($scope, $http) {
$scope.fetcheddata = [];
$scope.loading = false;
$scope.init = function() {
$scope.loading = true;
$http.get('/api/content').
success(function(data, status, headers, config) {
$scope.fetcheddata = data;
$scope.loading = false;
});
}
$scope.getDesc = function() {
$scope.loading = true;
$http.get('/api/content/get/' + item.id).
success(function(data, status, headers, config) {
$scope.fetcheddata = data;
$scope.loading = false;
});
}
$scope.init();
});
View Code:
<div class="col-xs-2 type-image" tr ng-repeat='item in fetcheddata'>
<a href="#" class="thumbnail click-productgroup" data-group="show-<% item.group %>">
<img src="<% item.image %>" class="img-responsive">
</a>
</div>
The -tag should fetch the item.description and update another div. How can I do that?
I tried with an getDesc scope. Is this right? But how do I updated the div?
EDIT 1:
<div class="row">
<div class="col-md-7" id="productGroups">
<div class="row type-row">
<div class="col-xs-2 type-image" ng-repeat='item in fetchedData'>
<a href="#" class="thumbnail" ng-click='getDesc(<% item.id %>)'>
<img src="<% item.image %>" class="img-responsive">
</a>
</div>
</div>
</div>
<div class="col-md-5 type-description">
<% fetchedDesc | json %>
</div>
</div>
and in my controller:
$scope.getDesc = function() {
$scope.loading = true;
$http.get('/api/content/get/' + item.id).
success(function(data, status, headers, config) {
$scope.fetchedDesc = data.description;
$scope.loading = false;
});
}
Still the page jumps on click to the top and no content in the div (although ng-binding appears in the html).
Firstly, the page is jumping because the href of your anchor tag is #, remove that to stop it from happening :).
Secondly, I think the best way of achieving what you're after would be to ensure that each item fetched from the server in the $http.get('/api/content') call has the description as a property, rather than fetching it seperately, and then do something like this:
$http.get('/api/content').
success(function(data, status, headers, config) {
$scope.items = data;
});
$scope.selectItem = function(item) {
$scope.selectedItem = item;
}
And in the view:
<div class="col-xs-2 type-image" tr ng-repeat='item in items'>
<a href="" class="thumbnail click-productgroup" ng-click="selectItem(item)">
<img src="{{ item.image }}" class="img-responsive">
</a>
</div>
<div>
{{ selectedItem.description }}
</div>
I notice that is your getDesc you don't pass item.id?
$scope.getDesc = function(item) {
$http.get('/api/content/get/' + item.id)
.then(function(data) {
console.log(data)
})
}
This should come from ng-click of the div tag?
<div class="col-xs-2 type-image" tr ng-repeat='item in fetcheddata'>
<a href="#" class="thumbnail click-productgroup" data-group="show-<% item.group %>" ng-click="getDesc(item)">
<img src="<% item.image %>" class="img-responsive">
</a>
</div>
I'm working on a blog like structured web app In AngularJS. Im trying to retrieve the user which is an other of a post and retrieve their display name dynamically as it loops through all the posts but I cant seem to retrieve data correctly.. This is what I have done so far.
Blog Controller:
uno.controller('newsCtrl', function($scope, $http, adbFactory){
$scope.derp = 'derp!!!!!';
adbFactory.get($http, 'get users 1', false).success(function(data){
$scope.user = data;
}).error(function(){
console.log('Errorrr');
});
$scope.init = function(){
adbFactory.get($http, 'get all blog_posts', true).success(function(data){
$scope.posts = data;
console.log($scope.posts);
});
};
$scope.getAuthor = function(_id) {
adbFactory.get($http, 'get users id ' +_id+ ' spec', false).success(function(data){
//$scope.author = data;
//console.log($scope.author);
return data;
});
};
});
If I console.log the data it shows the users perfectly given the author id which is in the database, but when i attempt to call the getAuthor function using the '{{ }}' scope i get a collage of errors... heres my blog template below.
Blog Template:
<div class="large-12 small-12 columns" ng-init="init()">
<div class="row">
<div class="large-12 small-12 columns" ng-repeat="topic in posts" style="margin-bottom:20px;">
<div id="news-post" class="panel animated fadeInUp">
<div class="row" ng-init="getAuthor(topic.author_id)">
<div class="large-2 small-2 columns">
<img src="{{ topic['thumb'] }}" alt="" style="border-radius:50%; height:100px; width: 150px;" />
</div>
<div class="left large-10 small-10 columns">
<div class="row">
<h2 class="post-title">{{topic['title']}} <p>Posted By, {{ getAuthor(topic.author_id).email }}</p></h2>
<p>{{ topic['body'] }}</p>
</div>
</div>
</div>
</div>
</div>
<hr>
</div>
</div>
not quite sure what the problem can be.. Any thing I'm missing?
UPDATE::
I recently updated my controller and factories to get a better scope of handling my data flow, my Controller now looks like this:
uno.controller('newsCtrl', function($scope, $http, adbFactory, $cacheFactory, unoFunctions){
$scope.init = function(){
adbFactory.get($http, 'get all blog_posts', true).success(function(data){
$scope.posts = data;
$scope.getUser = function(_id) {
$scope.userData = unoFunctions.getUser(_id);
//console.log($scope.userData);
return $scope.userData;
};
});
$scope.getTags = function(_id) {
var post = unoFunctions.getPost(_id);
var _tags = post.tags.split(',');
for(var i = 0; i < _tags.length; i++)
{
_tags[i] = _tags[i].trim();
}
return _tags;
};
$scope.getUserName = function(_id) {
$scope.userData = unoFunctions.getUser(_id);
return $scope.userData.display_name;
};
$scope.getUser = function(_id) {
$scope.userData = unoFunctions.getUser(_id);
//console.log($scope.userData);
return $scope.userData;
};
$scope.getUserName = function(_id) {
$scope.userData = unoFunctions.getUser(_id);
return $scope.userData.display_name;
};
};
});
the unoFunctions factory is wht I use now to handle certain requests from my database, and that is shown below.
uno.factory('unoFunctions', function(adbFactory, $http, $cacheFactory){
var fact = {};
var user = $cacheFactory('user');
var post = $cacheFactory('post');
fact.getUser = function(_id) {
if(!user.get(_id)){
adbFactory.get($http, 'get users id '+_id+' spec', false).success(function(data){
user.put(_id, data);
});
}
return user.get(_id);
};
fact.getPost = function(_id) {
if(!post.get(_id))
{
adbFactory.get($http, 'get blog_posts id '+_id+' spec', false).success(function(data){
post.put(_id, data);
});
}
return post.get(_id);
};
fact.loggedIn = function()
{
console.log('gfdg');
};
/*------------------------------*/
return fact;
});
And my template to output the result is this:
<div class="large-12 small-12 columns" ng-init="init()">
<div class="row">
<div class="large-12 small-12 columns" ng-repeat="topic in posts | filter:postTitle | orderBy:'-time' " style="margin-bottom:20px;">
<div id="news-post" class="panel animated fadeInUp" ng-init="getTags(topic.id)">
<div class="row" style="padding-bottom:0px;">
<div class="large-2 small-2 columns">
<img src="{{ topic['thumb'] }}" alt="" style="border-radius:50%; height:120px; width: 200px;" />
</div>
<div class="left large-10 small-10 columns">
<div class="row" style="padding-bottom:0px;">
<h2 class="post-title">
<a href="#/news/post/{{ topic['id'] }}">
{{topic['title']}}
</a>
<p style="font-size:13px; font-style:italic; color:#a5a5a5" class="right">{{ topic.time | timeago }} {{ }}</p>
<p style="font-weight:bold; font-style:italic; color:#aaa">Posted By, {{ getUser(topic.author_id).display_name }}</p></h2>
<p>{{ topic['body'] }}</p>
<div ng-repeat="tag in getTags(topic.id)"><span style="background:#ccc; margin:7px; padding:4px; border-radius:5px; font-size:12px" class="left">{{ tag }}</span></div>
<p class="right" style="background:#dedede; font-size:13px; padding:7px; border-radius:6px; color:#1985A1;">{{ topic.category }}</p
</div>
</div>
</div>
</div>
</div>
</div>
</div>
This works fine and returns the required results I'm looking for but I wish to get rid of the countless Error: [$rootScope:infdig] errors and keep my console clean.. I researched the error and it seems to be because when I call functions from the unoFunctions factory like, getUser, or getPost. it returns a new array each time or something like that which I guess throws things out of scope. I'm not entirely sure, and reason for this?
This binding
<p>Posted By, {{ getAuthor(topic.author_id).email }}</p>
assumes that getAuthor returns an object, but it doesn't, even with proper return statement - because asynchronous request takes place, and adbFactory chain will apparently return a promise, not an object. And doing adbFactory.get every time getAuthor bindings are being watched would be bad performance-wise - json result has to be parsed constantly, even with $http cache.
A suitable solution for caching and binding service results to the scope (and a precursor to full-blown model) is
var authors = $cacheFactory('authors');
$scope.getAuthor = function(_id) {
if (!authors.get(_id)) {
authors.put(_id, {});
adbFactory.get($http, 'get users id ' +_id+ ' spec', false).success(function(data){
authors.put(_id, data);
});
}
return authors.get(_id);
};
I have a categoriesPanel controller that on ng-click I want to show all the products belongings to that category inside my ng-controller productsPanel. The problem im having is that every time I click on the ng-click="selectorCategory" I get the all the products in the clicked category after I refresh the page.
<div class="col-md-6 m-t-10" ng-controller="productsPanel" style="padding-right:1px;">
<div class="panel panel-default" style="height: 700px">
<div class="panel-body">
<div ng-repeat="product in Products" class="productRow">
{{product.Product}}
</div>
</div>
</div>
</div>
<div class="col-md-3 m-t-10" ng-controller="categoriesPanel" style="padding-left: 0; padding-right: 5px">
<div class="panel panel-default" style="height: 700px">
<div class="panel-body">
<div ng-repeat="category in Categories" class="categoryRow">
{{category.Category}}
</div>
</div>
</div>
</div>
this is my angular script that is getting the right data from the backend but the data only shows in the producsPanel controller when i refresh the page. I want to data to show as soon as you do the ng-click.
app.controller('categoriesPanel', function($scope, $location, $http, $localStorage){
var CompanyId = $localStorage.Employee[0].CompanyId;
$http({
method : 'GET',
url : 'http://localhost:8888/categories/ajax_getCompaniesCategories',
params: {CompanyId: CompanyId}
})
.success(function(data){
$scope.Categories = data;
$localStorage.Categories = data;
});
$scope.selectedCategory = function(event){
$localStorage.CategoryId = $(event.target).data('id');
$http({
method : 'GET',
url : 'http://localhost:8888/products/ajax_getCategoryProducts',
params: {CategoryId: $localStorage.CategoryId}
})
.success(function(data){
$scope.Products = data;
$localStorage.Products = data;
});
}
});
app.controller('productsPanel', function($scope, $location, $http, $localStorage){
$scope.Products = $localStorage.Products;
});
/* END CONTROLLERS */
Maybe the product array you are pointing to gets clear when call to getcategoryproducts is made. Can you fix your callback for ajax_getCategoryProducts and change success to push elements into the array instead of reassignment.
.success(function(data){
$scope.Products.length=0;
data.forEach(function(p) {
$scope.Products.push(p);
});
$localStorage.Products = $scope.Products;
});
$scope.temp and $scope.description don't have values until ng-submit calls $scope.getWeather. I can log the values after submission, but can't update the view to display them. $scope.test is demonstrating that my view will only display "This is a DEFAULT value" and not update to "This is the NEW value" when $scope.getWeather is called. Thanks.
angular.module('forecastCtrl', ['weatherService'])
.controller('forecastController', function($http, $scope, Weather) {
//var vm = this;
$scope.test = 'This is a DEFAULT value';
$scope.getWeather = function(postData) {
Weather.get(postData)
.success(function(data) {
console.log(data);
$scope.test = 'This is the NEW value';
$scope.temp = data.query.results.channel.item.condition.temp;
$scope.description = data.query.results.channel.item.condition.text;
})
.error(function(error) {
console.log(error);
});
event.preventDefault();
};
// THIS IS THE FORM
<form name="getWeatherForm" action="#" ng-submit="getWeather(postData)" class="small-10 large-6 small-centered large-centered columns">
<div class="row collapse">
<div class="small-9 columns">
<input type="text" placeholder="Philadelphia, PA" ng-model="postData.city">
</div>
<div class="small-3 columns">
<button type="submit" class="button postfix">Go</button>
</div>
</div>
</form>
//THIS IS THE FACTORY
angular.module('weatherService', [])
.factory('Weather', function($http) {
return {
get: function(location) {
location = location.city;
location = location.replace(/\s/g, '');
// do error handling
return $http.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22'+location+'%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys');
}
}
});
// THE VIEW
<main id="content">
<div class="row">
<div class="small-12 large-12 columns">
<section class="wrapper">
{{ test }}
<h1>{{ forecast.temp }}</h1>
<h2>{{ forecast.description }}</h2>
</section>
</div>
</div>
The code is working, but the repsonse does not have the assumed properties when the city is not provided or wrong city is provided. So maybe use ng-required, as the code will fail if the postData.city is not set
http://plnkr.co/edit/7F3EUMyAXtAlBR9CGWb0?p=preview
.success(function(data) {
console.log(data);
$scope.test = 'This is the NEW value';
$scope.temp = data.query.results.channel.item.condition.temp;