Meteor JS Remove Single Element from Collection using _id - javascript

I am trying to remove a single document from the collection in over server side with Meteor.methods by passing _id of object ,but it is not removing object , also tried other fields in that document but no go.
I have also tried FoodCategory.remove(removeID) ; that is also not working.
File 1 - displayCategorySection.html
<template name="categoryDisplaySection">
<div class="row categoryDisplay">
<div class="col-md-10 col-lg-10 ">
{{Category}}
</div>
<div class="col-md-2 col-lg-2 pull-right">
<i class="fa fa-minus-square"></i>
</div>
</div>
<div class="row ">
<div class="col-md-12 col-lg-12 identity">
{{_id}}
</div>
</div>
</template>
In the .JS file I am passing this _id to Meteor method deleteFoodCategory
File 2 - categoryDisplaySection.js
Template.categoryDisplaySection.events({
'click .fa-minus-square':function(evt,tmpl)
{
var remove_id = tmpl.$(".identity").text();
alert(remove_id);
/*****Server side call for document remove *****/
Meteor.call("deleteFoodCategory",remove_id,
function(error,result)
{ alert(result); });
}
});
Server Side File 3 - FoodCategorySection.js contain deleteFoodCategory method
Meteor.methods({
deleteFoodCategory: function(removeID)
{
return FoodCategory.remove({
'_id' : removeID
},
function(error,id)
{
if(id) { return id;} else { return error; }
});
}
});
Code is working correctly if I put _id like "RAEnLfomeqctuonnE" in place of variable removeID. I tried various options like '_id' or just _id without quotes , unable to figure out problem.Please take a look

Fetching the document _id from a div text is overkill, you could use the current data context instead :
Template.categoryDisplaySection.events({
"click .fa-minus-square": function(evt,tmpl){
var removeId = this._id;
alert(removeId);
Meteor.call("deleteFoodCategory", removeId);
});
In your Meteor method, you can simply pass the _id to Collection.remove :
Meteor.methods({
deleteFoodCategory: function(removeId){
return FoodCategory.remove(removeId);
}
});

Answer provided by saimeunt is also working correctly as far as original problem is concern , there is need to use .trim function with remove_id variable
File 2 - categoryDisplaySection.js
Template.categoryDisplaySection.events({
"click .fa-minus-square": function(evt,tmpl){
var remove_id = tmpl.$(".identity").text();
/**This line needed to be added**/
removeId = remove_id.trim();
alert(removeId);
/*****Server side call for data insert *****/
Meteor.call("deleteFoodCategory",removeId);
})
but as #saimeunt has said fetching the document _id from a div text is overkill,so using this_id from now on

Related

How to use localStorage value filter in ng-repeat

I've set a value when the user click vote choice. Its working.
.then(function(response) {
localStorage.setItem('isClicked', 'Yes');
var i = +localStorage.key("nid");
var nidId = 'nid' + localStorage.length;
localStorage.setItem(nidId, vm.nid);
vm.clickedBefore = true;
})
This is my HTML scope:
<div class="card myfunc" ng-repeat="myfunc in myfuncPage.myfuncs" id="{{myfunc.nid}}" >
<div class="item item-text-wrap">
<h2 class="item-icon-left"><i class="icon ion-ios-analytics"></i>
{{myfunc.title}}</h2>
</div>
<div class="item item-text-wrap" ng-show="localstorage">
<img ng-src="{{myfunc.field_image.und[0].imgPath}}"/>
<p class="custom-class" ng-bind-html='myfunc.body.und[0].value'>
</p>
<ul ng-repeat="vote in myfunc.advmyfunc_choice">
<li ng-repeat="voteselect in vote">
<div class="row">
<button class="col button button-outline button-dark" ng-click="myfuncPage.sendNid(myfunc);myfuncPage.sendVote(voteselect);showVoted = ! showVoted" >{{voteselect.choice}}</button>
<div class="voted-screen" ng-show="showVoted">
<h3>Thanks.</h3>
</div>
</div>
</li>
</ul>
</div>
</div>
In basically, I need remember the div via localStorage and when the page refresh, hide choice divs.
ng-show="showVoted" working on click but I need on refresh.
What is the best way to do it? Thanks.
I am not sure what local storage module you are using, so I can't be specific, but I would write factory that handles the retrieval and storage of the values you need
(function () {
var voteFactory = function (localStorage) {
return {
getVote: function (key) {
var isVoted = false;
// get local storage item, set voted etc
var voted = localStorage.getItem(key);
if(voted) {
isVoted = voted;
}
return isVoted;
},
setVote: function(key, value) {
localStorage.setItem(key,value);
}
};
};
app.factory('voteFactory', ['localStorage', voteFactory]);
})();
Then within the scope controller/directive you are using to show or hide you would have a function:
$scope.showVoted = function(key) {
return voteFactory.getVote(key);
}
then ng-show="showVoted(theidentifieryouwantouse)"
It is also worthwhile to mention I would use ng-if instead of ng-show. To be more efficient you could store your votes as an array instead of individual values and do a check to see if you have retrieved all values, get from local storage if not. Then your functions would interrogate retrieved array instead of repeated calls to local storage. I would also advice maybe using a promise in the factory because retrieval from local storage could be delayed causing some ui oddities.
Hopefully this is along the lines of what you are looking for. I can elaborate if needed.

Angular scope not updating when passed in object to function

I have a controller function which is called on double click of an item in an ng repeat:
$scope.likeUpdate = function(update) {
$http.post( $rootScope.apiURL + 'likeupdate', {
update_id : update.data.id,
user_id : $rootScope.currentUser.id
}).success(function(result, response){
update.data.does_like = result[0][0].does_like;
console.log(result[0][0].does_like);
});
}
This, should to me, change on my Ionic app and update on the screen the 'does_like' value.
However, it doesn't.
Here is my ng repeat:
<div ng-repeat="update in updates" class="custom-card">
<div ng-show="{{update.image}}" class="image">
<img on-double-tap="likeUpdate({{update.data.id}})" class="full-image" ng-src="https://s3-eu-west-1.amazonaws.com/images/{{update.image.name}}" imageonload>
</div>
{{ update.data.does_like }}
</div>
On page load, the update.data.does_like correctly shows what I need, and after page refresh will show what It should. But in my code its not updating live on the success callback.
The console log shows the correct output.
P.S I know doing result[0][0] isn't good, shall be working on structure soon.
In order for likeUpdate to change the data.does_like property of the update in question, you should pass the update to it instead of whatever {{update.data.id}} resolves to, ie
<img on-double-tap="likeUpdate(update)" ...
While we're making changes, you should remove the deprecated success method
$scope.likeUpdate = function(update) {
$http.post($rootScope.apiURL + 'likeupdate', {
update_id : update.data.id,
user_id : $rootScope.currentUser.id
}).then(function(response) {
update.data.does_like = response.data[0][0].does_like;
});
};
update is a local variable to the function.
try
$scope.updates = result[0];
But your structure looks off.

How to access functions of a controller from within another controller via scope?

I have the following problem, I want to call a function of another controller from within a controller I want to use for a guided tour (I'm using ngJoyRide for the tour). The function I want to call in the other controller is so to say a translator (LanguageController), which fetches a string from a database according to the key given as parameter. The LanguageController will, if the key is not found, return an error that the string could not be fetched from the database. In my index.html fetching the string works, but I want to use it in the overlay element of my guided tour, which does not work, but only shows the "not fetched yet"-error of the LanguageController.
My index.html looks like this:
<body>
<div class="container-fluid col-md-10 col-md-offset-1" ng-controller="LangCtrl as lc" >
<div ng-controller="UserCtrl as uc" mail='#email' firstname='#firstname'>
<div ng-controller="GuidedTourCtrl as gtc">
<div ng-joy-ride="startJoyRide" config="config" on-finish="onFinish()" on-skip="onFinish()">
...
{{lc.getTerm('system_lang_edit')}}
...
</div>
</div>
</div>
</div>
</body>
The controller I'm using for the guided Tour looks like this:
guidedTourModule.controller('GuidedTourCtrl',['$scope', function($scope) {
$scope.startJoyRide = false;
this.start = function () {
$scope.startJoyRide = true;
}
$scope.config = [
{
type: "title",
...
},
{
type: "element",
selector: "#groups",
heading: "heading",
text: " <div id='title-text' class='col-md-12'>\
<span class='main-text'>"\
+ $scope.lc.getTerm('system_navi_messages') + "\
text text text text\
</span>\
<br/>\
<br/>\
</div>",
placement: "right",
scroll: true,
attachToBody: true
}
];
...
}]);
And the output I ultimately get looks like this for the overlay element:
<div class="row">
<div id="pop-over-text" class="col-md-12">
<div id='title-text' class='col-md-12'>
<span class='main-text'>
not fetched yet: system_navi_messages
text text text text
</span>
<br/>
<br/>
</div>
</div>
</div>
...
I hope someone can see the error in my code. Thanks in advance!
Things needs clarity are,
How you defined the 'getTerm' function in your Language controller, either by using this.getTerm() or $scope.getTerm(). Since you are using alias name you will be having this.getTerm in Language controller.
Reason why you are able to access the getTerm function in your overlay element is, since this overlay element is inside the parent controller(Language Controller) and you are referencing it with alias name 'lc' while calling the getTerm function. Thats' why it is accessible.
But the string you pass as a parameter is not reachable to the parent controller. that's why the error message is rendered in the overlay HTML.
Please make a plunker of your app, so that will be helpful to answer your problem.

Ember.js: Deleting an Item from a Sorted ArrayController

In the Ember app I'm building, I've got an ArrayController managing a list of items with several columns of data for each record object in the array with a sort button in each column header in the view. I have set up the list to sort on a given column per Balint Erdi's recommended method here. You will see this sorting in my code below.
The sorting works fine. However, the problem arises when I remove an item from the array. Currently, when I attempt to remove an item from the array, the correct item is apparently removed from the array and is properly deleted from the store and the delete is saved to my backend. However, after the item removal, my view is not correct. In some cases, the wrong item is shown as removed, in other cases, no item is shown as removed. Yet IF I press sort again, the view is updated correctly.
So, the index of the array is obviously getting off some how, but I'm not sure how and all of my attempts to apply the tricks of others are not working!
Here is my route object:
App.UsersFilesRoute = Ember.Route.extend({
model: function () {
return this.modelFor('users').get('files');
}
});
Here is my ArrayController:
App.UsersFilesController = Ember.ArrayController.extend({
sortProperties: ['name'],
sortedFiles: Ember.computed.sort('model', 'sortProperties'),
actions: {
addFile: function(file) {
var newFile = this.store.createRecord('file', {
name: file.name.trim(),
fileSize: file.size,
loaded: false
});
this.pushObject(newFile);
},
sortBy: function (sortProperties) {
this.set('sortProperties', [sortProperties]);
},
removeFile: function (fileToRemove) {
var _this = this;
var file = this.store.find('file', fileToRemove.get('id'));
file.then( function (file) {
_this.removeObject(file);
file.deleteRecord();
file.save();
});
},
saveFile: function (file) {
....
}
}
});
And here is my template code:
<div class="hidden-xs row user-file-header-row">
<div class="col-sm-5 col-md-5 user-file-header">
File Name
<button type="button" class="btn-xs btn-default files-sort-btn" {{ action 'sortBy' 'name'}}></button>
</div>
<div class="col-sm-1 col-md-1 user-file-header">
Size
<button type="button" class="btn-xs btn-default files-sort-btn" {{ action 'sortBy' 'fileSize'}}></button>
</div>
</div>
{{#each file in sortedFiles}}
<div class="row user-file user-file-break">
<div class="col-xs-11 col-sm-5 col-md-5 user-file-name">
<a {{ bind-attr href="file.path" }} >{{ file.name }} </a>
</div>
<div class="col-xs-9 col-sm-1 col-md-1">
{{ format-file-size file.fileSize }}
</div>
<div class="col-xs-9 col-sm-1 col-md-1">
<button type="button" class="btn-xs btn-default files-list-btn" {{ action 'removeFile' file }}></button>
</div>
</div>
{{/each}}
NOTE: There is some similarity between my question and this other StackOverflow question: After using jQuery UI to sort an Ember.js item, using Ember Data's model.deleteRecord() doesn't work, however, I've attempted to apply that answer my own problem with no success. Furthermore, I have no jQuery going on here in my sorting.
OK. I have found an answer, or rather an answer has found me.
My problem was that in the code above I was removing the itemfrom the ArrayController and then calling .delete() and .save(). This sequences of calls was sending conflicting signals to Ember on how to update my view. Apparently, the .removeObject() was actually removing the item from the array, but then the subsequent .delete()/.save() was setting the model behind the view to a state just before deletion (not sure about that but that's what I saw happening).
So anyways, .destroyRecord() returns a promise, so I moved the .removeObject() within the .then() for the promise, and that resolves the issue.
So, the following code in the removeFile action resolved the issue:
removeFile: function () {
var self = this;
var fileToRemove = this.get('fileToRemove');
var file = this.store.find('file', fileToRemove.get('id'));
file.then (function (file) {
file.destroyRecord().then(function(){
self.get('model').removeObject(file);
});
});
}
Note that you don't have to do the this.store.find() first, you could simply do the following:
removeFile: function () {
var self = this;
var fileToRemove = this.get('fileToRemove');
fileToRemove .destroyRecord().then(function(){
self.get('model').removeObject(file);
});
}
However, I chose to be conservative and double-check the store. That seems safer to me.

How do you apply an item, from a list of results, to the parent Div tag for the current object?

I am trying to build a function for inserting the number of Facebook Likes into a Div tag. So far, I have a script that can get the URL from a Div tag which is inside of another Div tag called 'entry' and then have the .getJSON() method retrieve the number of Facebook likes for each entry.However, I can't get each retrieved value of Facebook Likes to insert into a Div tag for each entry. Please note, I simplified my code to where it alerts each Facebook Like value. This is what I have so far:
<div class="entry">
<div class="fburl">https://graph.facebook.com/zombies</div>
<div class="facebook-likes"></div>
</div>
<div class="entry">
<div class="fburl">https://graph.facebook.com/starwars</div>
<div class="facebook-likes"></div>
</div>
And here's my jQuery:
$(document).ready(function(){
$(".entry").each(function() {
var fbURL = $(this).find(".fburl").html();
$.getJSON(fbURL, function(fbData) {
var fbArr = fbData['likes'];
alert(fbArr);
});
});
});
​So what I am trying to do is iterate through each entry, get the Open Graph URL for it, retrieve the Likes value, and then insert it into the appropriate Div tag, so the code should render as:
<div class="entry">
<div class="fburl">https://graph.facebook.com/zombies</div>
<div class="facebook-likes">2,586 Likes</div>
</div>
<div class="entry">
<div class="fburl">https://graph.facebook.com/starwars</div>
<div class="facebook-likes">8,905,721 Likes</div>
</div>
​
​
$(document).ready(function() {
$('.entry').each(function() {
var $this = $(this),
fbURL = $this.children('.fburl').html();
$.getJSON(fbURL, function(fbData) {
$this.children('.facebook-likes').html(fbData['likes'] + ' Likes')
});
});
});
See: http://api.jquery.com/children
Demo: http://jsfiddle.net/9EALz/2/
Note: Using children() is going to be marginally more efficient than using find() as it limits the DOM traversal to a single level ( http://jsperf.com/find-vs-children/13 ). Cashing the jQuery object $(this) via var $this = $(this) is also slightly more efficient as it prevents unnecessary selector interpretation ( http://jsperf.com/jquery-cache-vs-no-chace ).
You may want this
$(document).ready(function(){
$(".entry").each(function() {
var entry=$(this), fbURL=$(".fburl", entry).html(),
el=$('.facebook-likes', entry);
$.getJSON(fbURL, function(fbData) {
el.html(numberWithCommas(fbData['likes'])+" Likes");
});
});
});​
A thousand separator function from here
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
DEMO.
Update:
Alternatively you can use this too (using data-attribute) without an extra div for fburl, i.e.
<div class="entry">
<div data-fburl="https://graph.facebook.com/zombies" class="facebook-likes"></div>
</div>
JS
$(".entry").each(function() {
var entry=$(this), fbURL = $(".facebook-likes", entry).attr('data-fburl'),
el=$('.facebook-likes', entry);
$.getJSON(fbURL, function(fbData) {
el.html(numberWithCommas(fbData['likes'])+" Likes");
});
});

Categories

Resources