Cannot access proper firebase item key to pass to delete function - javascript

Having a sticky issue with firebase. I am trying to get access to the long format ID which firebase auto-generates for each collection item (eg. -JgnIsMlTLaPuDMEtQP2) to pass to my delete function. I previously got it to work in a different angular app as follows:
HTML
<tbody ng-repeat="(key,employee) in employees">
<tr>
<td>{{employee.employeeName}}</td>
<td>{{employee.employeeAge}}</td>
<td>{{key}}</td> // the key param appeared perfectly in this case
<td>
<button class="btn btn-danger"
ng-click="deleteEmployee(key, employee.employeeName)">
delete <span class="glyphicon glyphicon-remove"></span>
</button>
</td>
</tr>
</tbody>
Javascript
$scope.deleteEmployee = function(key,name) {
// get ref to db collectionvar employeeRef = new Firebase("https://xxxxxxx.firebaseio.com/Employees");
// append item key to the path and run remove method
var newRef = employeeRef.child(key);
newRef.remove();
// confirm delete
alert(name + " has been deleted");
}
The above code receives the correctly formatted key and deletes the item perfectly - which is immediately reflected in the view.
However, I'm trying it with a different app and the key value is being set to an incremental index (eg. 0,1,2,3,4...) and so it doesn't work when passed to the delete function. Here is the new code.
HTML
<div class="row">
<ul id="messages" ng-show="messages.length">
<li ng-repeat="(key, message) in messages | reverse">{{message.text}}
<small>{{key}}</small> // WRONG VALUE DISPLAYED HERE
<button class="btn btn-xs btn-danger" ng-click="delMessage(key)" label="Remove">Delete</button>
</li>
</ul>
</div>
Javascript
//delete message
$scope.delMessage = function(messageKey) {
var messageRef = new Firebase('https://xxxxxx.firebaseio-demo.com/messages/');
// append item key to the path and run remove method
var messageRef = messageRef.child(messageKey);
if( messageRef ) {
messageRef.remove();
console.log("DEL: " + messageRef); // this logs the endpoint with index number
console.log("Message removed successfully!");
} else {
console.log("uh oh...problem!");
}
};
The format of messageRef when logged to console is
https://xxxxxx.firebaseio-demo.com/messages/2
but instead should be
https://xxxxxx.firebaseio-demo.com/messages/-JgnIsMlTLaPuDMEtQP2
I have tried every combination that I could find to get it to work but nothing fixes it so far. I'm not sure why it would work in the first piece of code and not the second. The only thing I can add is the app that isn't working was created via firebase-tools in the terminal whereas the working app is just some angular code with firebase bolted on. I have also tried changing remove() to $remove but that throws undefined method errors. I'm totally stumped. Any assistance is appreciated.

Following Frankvan's advice I sourced a snippet from angularFire quickstart docs which allowed me to simply pass the current selected message directly to angularFire's $remove method, avoiding the need to pass a specific message id.
<li ng-repeat="message in messages">
.......
<!-- delete message -->
<button ng-click="messages.$remove(message)">X</button>
</li>
Even though this works, I wanted to add some extra code and decouple the JS from the HTML a bit more. I decided to set up a custom function in the angular controller to handle it and call this function from the ng-click.
The following code works exactly the same as above but adds a prompt for the user to confirm the delete before calling the $remove.
HTML:
<button ng-click="deleteMessage(message)">x</button>
Angular function:
// delete a specific message
$scope.deleteMessage = function(message) {
var msg = JSON.stringify(message.text);
if(message) {
var confirm = window.confirm("Are you sure you want to delete: " + msg + "?");
if(confirm == true) {
$scope.messages.$remove(message).then(function(){
alert("Message " + msg + " has been deleted!");
console.log("Message was removed successfully from firebase!");
});
}
} else {
console.log("Sorry, there was a problem deleting the message.!");
}
};

I beat my head against this problem on a project of mine for awhile. The key is to use the $loaded method of Angular Fire to wait for the object to get populated prior to calling the $remove method because these calls are asynchronous.
https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray-loaded

Related

Micrsoft Dynamics CRM: Facing troubling while executing js web resouce for crm button

I created a button in an account form entity by ribbon workbench and then I tried to create a javascript code. When executed the code is just fetching the account id and showing that id in the alert and then I registered that file to that button by ribbon workbench action command.
I wrote the below code, please let me know what is wrong with that.
I am expecting an alert box with that id, but nothing is happening
The code is below:
fetch = {
fetchingacountid: function(executionContext){
var formContext = Xrm.Page.context.getFormContext();
var accountId = formContext.data.entity.getId();
alert("The ID of the current account is: " + accountId);
}
}
Possibly you might have missed to add the PrimaryControl CRM parameter in ribbon command. Then you don’t need Xrm.Page, instead you will get the context directly in the first parameter executionContext. Read more

AngularJS Delete function REST HTTP://1.1 500 Error

I am using AngularJS to delete a row via a REST API. When I click the link for the function to delete the row, I get a Internal Server Error. I'm asking how to fix the form to get it to delete the row.
//CONTROLLER to delete a specific item
countryApp.controller('DeleteLocation', function($scope, $http, $routeParams, $location) {
//get item info
var id = $routeParams.locid;
$scope.activePath = null;
$http.get('http://localhost/slimtest2/location/'+id).success(function(data) {
$scope.location= data;
});
//add more stuff here
$scope.pedelete = function(id) {
$http.delete('http://localhost/slimtest2/location/1/delete', id);
}
});
View for Deleting a Row
<div ng-controller="DeleteLocation">
<div ng-repeat="l in location.location">
Are you sure you want to delete the location named: {{l.location_title }}
Delete This
</div>
</div>
Internal Server error occurs when something happens wrong at server-side. Please check your server-side code/configuration are proper or not.
A couple of points to check:
1. Is your request method type "get" for a delete request as well or should it be "delete"? For this you need to check which method type your API is expecting. You may want to use $http.delete() instead.
2. Check your browser console/network. Are you seeing the error there? If so, work out on the error to resolve the issue. The error description should be coming what your API is sending.
Hope this helps.

Call model function from JavaScript in Laravel

I'm actually running into little problems with my current project. Following case:
I've got a model called "Posting" with relations:
public function subscribers(){
return $this->belongsToMany('User');
}
In my view-file there is a table containing all Postings and also a checkbox for subscribing/unsubscribing with the matching value to the posting-id:
<input class="click" type="checkbox" name="mobileos" value="{{{$posting->id}}}"
#if($posting->subscribers->find(Auth::User()->id))
checked="checked"
#endif
>
Now the thing I want to archive:
A JavaScript is going to watch if the checkbox is checked or not. According to that, the current user subscribes/unsubscribes to the posting. Something like:
$('.click').on('click',function() {
// $posting->find(---$(this).prop('checked')---)->subscribers()->attach(---Auth::user()->id---);
// $posting->find(---$(this).prop('checked')---)->subscribers()->detach(---Auth::user()->id---);
});
Is there any possibility to archieve that or any other ways? I couldn't get my head around this so far.
Cheers,
Chris
If you want to use Ajax to achieve this, you will need a REST endpoint in Laravel for the subscriptions, e.g.:
http://localhost/subscribe/{{userid}}
When this Endpoint is called, the database can be updated. The function could also return a JSON showing, if the saving database in the database successful.
Use this endpoint to make an Ajax Call on click:
var user = {
id: 0 // retrieve the correct ID from wherever it is stored
}
$('.click').on('click',function() {
$.GET('http://localhost/subscribe/' + user.id,
function () { // this is the success callback, that is called, if the Ajax GET did not return any errors
alert('You are subsribed')
});
});
Ideally you won't be using the GET method, but instead use POST and send the user ID as data. Also you would need to retrieve the user ID from session or wherever it is stored.
Take care that as you are using Ajax it can easily be manipulated from the client side. So on the server you should check, if the user ID that was sent is the same as in the Session. Maybe you don't need to send the user id at all, but that depends on how your backend is built.

Deleting Specific Record Using ObjectID

I'm defining a delete function in which, there's a delete button in each row, sending the ObjectID of that specific record to my Server Side, therefore, this ObjectId will be checked with the one stored in the database, resulting in deletion of that certain record, so far I could have make a good progress sending data's over, and checking on it, but I"m suspecting the ObjectId being sent, requires some sort of casting. Currently, the code and responses are as below;
Front-End (Index.Html)
<a href="#" class="list-group-item active" >
List Of Notes
</a>
<a href="#" class="list-group-item" ng-repeat="r in retrieve" >
{{r.create_at}}
<button style="float:right" type="button" ng-click="delete_note(r.ObjectId)"
class="btn btn-danger btn-xs">
Delete <i class="fa fa-trash"></i>
</button>
</a>
AngularJS (main.ctrl.js)
$scope.delete_note = function (data_id) {
$http.get('/delete_note', {
params: data_id
}).success(function(data){
console.log(data)
});
}
Back-End (Root.py)
#cherrypy.expose
#cherrypy.tools.json_out()
#cherrypy.tools.json_in()
def delete_note(self,*args,**kwargs):
res2=self.my_app.delete_note(kwargs)
return "<h1>delete success </h1>" +str(res2)
pass
Back-End (App.py)
def delete_note(self, index):
return self.db.notes.remove({'_id': index})
The current message appears in Google Chrome Console.log is this :
<h1>delete success </h1>{'ok': 1, 'n': 0}"
Which is obviously stating that, nothing has been changed within the database, I'm using Cherrypy, Mongodb, and Angularjs, any consideration is appreciated.
It'll be hard to locate the exact problem, but there are a few things that call for attention:
As nnnnnn already pointed out, nesting a button in an anchor (a) element is odd and might lead to weird issues.
The directive ng-click="delete_note(r.ObjectId)" looks odd: Does your python code really remap the _id field to a field called ObjectId? ObjectId is the type of (default) keys in MongoDB, the convention for the name is _id.
To find out, take a look at the network inspector when you GET the original data (i.e., $scope.retrieve) - what does it send? It's also helpful for debugging to output <pre>{{retrieve | json}}</pre> so you can see what ends up at angular
You're apparently deleting using a GET. While there's nothing that prevents you from doing that, writing with GETs is bad practice. If you possibly can, delete using an HTTP DELETE. If that's completely impossible for whatever reason, at least use a POST. But a GET should be nullipotent, i.e. it shouldn't change the server state at all.
The parameter to a REST request should be part of the URL, so your delete should read
DELETE /notes/:noteId, e.g. DELETE /notes/54fadec1e4259ded64c7576a
Putting the identifying parameter somewhere else violates the idea of resource urls.

Add items one at a time to a "cart" using checkboxes with Django, Ajax, and Jquery

New code now included, but still not working...
I am trying to use checkboxes to select an item(s) an add it to the "cart" at the top of the page. Every item on the page has a checkbox next to it that, when selected, should add the item to the cart and display that item name in the "cart" section at the top of the page. So, as the user goes down the page and checks an item, I want that item name to appear in the "cart" section at the top of page.
(i.e. check an item and the item name appears at top of page; check another item and that item name appears beside the first item at the top of the page; etc.)
With previous versions of my code, I have been able to get the first item listed on the page (and only the first item) to actually show in the "cart" section. I have tried everything I can, but I am completely new to Django, Ajax, and Jquery. Can someone please help!? Thank you!
"cart" section of list.html:
<div id="programCart">
<table cellpadding="5" cellpadding ="2" border="2" id="selected_programs_cart">
<tbody>
<tr>
<td id="selectionsHere"> SampleSelection1 </td>
</tr>
</tbody>
</table>
</div>
html that lists the items with a checkbox next to each, part of list.html (these items are displayed with a larger 'for' loop):
<td>
<form id="programs-selected" method="GET" action="select_citations">
<script type="text/javascript" src="/static/js/citations.js"></script>
<ul>
<li><input type="checkbox" id="programCheckbox" name="programs_to_add" value="{{software.id}}" />
</li>
</ul>
</td>
</form>
selectitems.js:
$('#programCheckbox').click(function(){
var softwareID
softwareID = $(this).attr("value")
$.get('add_to_cart', function(data){
$tbody = $("selected_programs_cart").find('tbody');
$.each(data, function(){
var displayCart = json.addingToCart;
for (var key in displayCart)
if (key == 'cart'){
var value = displayCart[key];
for (var softwareName in value)
$("<td>" + softwareName + "<td>").appendTo($tbody);
};
});
});
});
itemview.py
def add_to_cart(request):
#dict of 'cart' to list of selected programs to return
to_JSON = {}
#Programs are already in the cart and the "cart" key already exists in the session-
if 'cart' in request.session:
logger.warning("cart found")
software_id = request.GET.get('softwareID')
softwareObject = Software.objects.get(pk='software_id')
softwareName = softwareObject.title
addingToCart = request.session.get('cart')
request.session['addingToCart'].append(softwareName)
to_JSON = request.session['addingToCart']
#first time clicking on a program, no existing cart in session: the session should store 'cart' as the key and a list of selected programs as the value
else:
logger.warning("cart not found")
#get the softwareID of the most recently clicked program
software_id = request.GET.get('softwareID')
if software_id == None:
#oops, can't retrieve this from the request
logger.warning("cannot find software_id in the request")
return HttpResponse(request) # TODO: there's probably a better way to handle this
else:
logger.warning( "request.GET.get('softwareID'): {}".format(request.GET.get('softwareID')) )
try:
softwareObject = Software.objects.get(pk='software_id')
except Software.DoesNotExist as e:
logger.warning("oh oh, Someone is trying to access a Software ID that doesn't exist: {}".format(e))
# TODO: what to do if this happens?
except ValueError as e:
logger.warning("oh dear: {}".format(e) )
#TODO: if an exception happens, the softwareObject won't exist, what should happen then?
softwareName = softwareObject.title
#create an entry in the session dictionary for the cart and program list
request.session['cart'] = []
#add the first selected program to the list
request.session['cart'].append(softwareName)
addingToCart = request.session['cart']
to_JSON = request.session['addingToCart']
response_data = json.dumps(to_JSON)
return HttpResponse(response_data, content_type='application/json')
#return HttpResponse(json.dumps(cart, ensure_ascii=False), content_type='application/json')
This question is fairly broad, and will most likely get closed or downvoted out of existence, but I thought I'd try to steer you in the right direction.
Your view function is pretty far from being able to return JSON that your jQuery method can consume and use to update the DOM. Here's some pseudo-code:
import json
from django.http import HttpResponse
# or if you're using Django 1.7, you can use the JsonResponse class:
# https://docs.djangoproject.com/en/1.7/ref/request-response/#jsonresponse-objects
from your_app.models import Software
def add_to_cart(request):
# get an existing cart from the request
cart = request.session.get('cart', {'items': []})
# get the objects for the ids in the request
software_ids = request.GET.getlist('software_ids')
software = Software.objects.filter(id__in=software_ids)
# append the items to the cart
cart['items'].append(software)
# set the cart into session so you can persist it across requests
request.session['cart'] = cart
# dump the cart to JSON and send back a the response
return HttpResponse(json.dumps(cart, ensure_ascii=False),
content_type='application/json')
Something important to keep in mind here is that anything you want to put into session has to be serializeable to a string. The jsonpickle module is great for encoding/decoding complex Python objects to JSON.
Keeping concerns separate, you might want to pass the data returned from the response to a JavaScript templating function, like Underscore's _.template() and pass it the data from the response, rather than return HTML from the view.
There are also pre-made carts for Django: django-cart and django-carton. There's also this comparison chart of Django e-Commerce packages. Hope that gets you going.

Categories