Currently I am working on an angularJS app. it reads an property file from a repository and output an xeditable table, so you can change all the properties.
The only question I have now is, how do I make http.put request to update data.
assume the properties file have:
var data = {'prop1' : 'this', 'prop2' : 'that'};
I currently have:
$scope.update = function(key,value){
$http.post('http://blabla.com/properties.json', $scope.data)
.success(function (data, status) {
//success code
})
So Assume I updated the prop1 from this to newProperty.
Is my code correct? does the file in remote repository get updated?
or do i have to do something like this
$scope.update = function(key,value){
$http.post('http://blabla.com/properties.json',
data: {
prop1: 'newProperty'
})
.success(function (data, status) {
//success code
})
I only changed prop1, do I need to include prop2 also inside the data bracket? What happen when i got like 30 properties, then how do I update only 1 of the values using Http.put?
thanks
That URL won't work. You need a server-side API that can handle file uploads. That's not possible with Angular alone.
e.g.
$http.put('http://blabla.com/properties_api', $scope.data);
Also you've written $http.post up there, and that will (and should) fail unless the data doesn't exist in your repository. Change it to put if you're updating, 'post' only if you're creating.
Generally, uploading the full object is the way to go, otherwise the server is likely to treat the lack of other data as an explicit intention to delete that data. If you've got 30 properties, upload all 30.
That depends on how your server code handles this upload. If you write it yourself it'll do whatever you want with the data you give it.
That being said, if you've got a lot of data it can be unfeasible to upload it all, so you can create multiple APIs that can each handle a particular type of data.
e.g.
$http.put('http://blabla.com/properties_api/prop1_handler', $scope.data);
Related
I have a problem with a meteor publication not being reactive when using a query inside it.
Let's say I have many files, and each file has many projects, so I can go to the route:
http://localhost:3000/file/:file_id/projects
And I would like to both display the projects of the selected file and add new projects to it.
I am currently using angularjs, so the controller would look something like this:
class ProjectsCtrl {
//some setup
constructor($scope, $reactive, $stateParams){
'ngInject'
$reactive(this).attach($scope)
let ctrl = this
//retrieve current file id
ctrl.file_id = Number($stateParams.file)
//get info from DB and save it in a property of the controller
ctrl.subscribe('projects', function(){return [ctrl.file_id]}, function(){
ctrl.projects = Projects.find({file_id: ctrl.file_id}).fetch()
})
//function to add a new project
ctrl.addProject = function(){
if(ctrl.projectName){
Meteor.call('projects.insert', {name: ctrl.projectName, file_id: ctrl.file_id }, function(error, result){
if(error){
console.log(error)
}else{
console.log(result)
}
})
}
}
}
}
The publication looks something like this:
Meteor.publish('projects', function(file_id){
return Projects.find({file_id: file_id})
})
The problem is that, if I insert a new project to the DB the subscription doesn't run again, I mean the array stays the same instead of displaying the new projects I am adding.
I got many problems with this as I thought that meteor would work something like: "Oh there is a new project, let's re run the query and see if the publication change, if it does, let's return the new matching documents"... but no.
I have not found a problem similar to mine as every question regardind querys inside the publication is about how to reactively change the query (the file_id in this case) but that is not the problem here as I don't change the file_id unless I go to another route, and that triggers a new subscription.
My current solution is to expose the complete collection of projects and make the query using minimongo, but I don't know if it is a good workaround (many projects exposed uses too much memory of the browser, minimongo is not as fast as mongo... etc, I don't really know).
Your issue is that the Meteor.subscribe call doesn't know that file_id has changed. There's no reactive relationship between that argument and executing the subscription.
To fix this, whenever you are passing criteria in publish-subscribe, you must write a subscription of Collection inside a tracker.
To know more about trackers, Click here.
While I'm unsure how to do this in Angular, consider this simple Blaze template as an example:
Template.Name.onCreated(function(){
this.autorun(() => {
Meteor.subscribe('projects', file_id);
});
});
Whenever file_id changes, a new subscription is triggered, giving you the desired effect of auto pub-sub utility.
I hope this will give you some insight. It could be easily achieved via Angular JS as well.
I have a picture, profile.jpg on my server. When I upload a new picture, replacing picture.jpg in data but not in name (in other words, the old profile.jpg gets replaced by the new profile.jpg, but the new one is also called profile.jpg). After my promise is returned, I call forceUpdate, but this doesn't do anything unless I change the actual url (src) of the image. See my code, in which I attempted to concatenate promises in order that react would recognize that the url is changing (from the correct url, to "empty", to the correct url again):
fetch('http://localhost:3000/change_pet_pic/?petID='+this.props.pet.id+'&userID='+this.props.pet.ownerID, { method: 'POST', body: form })
.then(function(res) {
return res.json();
}).then(function(json) {
var pet = $this.props.pet;
pet.petPicture = "empty";
$this.props.pet=pet;
$this.forceUpdate();
return json.picture_url;
}).then(function(url){
var pet = $this.props.pet;
pet.petPicture = url;
$this.props.pet=pet;
$this.forceUpdate();
})
Thanks for your tips!
It seems nothing wrong with your ReactJS code instead it should be a browser cache which is causing issue by returning the old image all the time as the image url looks same.
What you can do to get rid of this is, you can access the image with different query string whenever the image is getting changed.
So the first time, you can access this with profile.jpg?v=1 and the second time, you can access it with profile.jpg?v=2 something like that.
Been wrestling with API stuff all day, and decided to use Restanglar. Really having issues getting the data out, and into $scope.
I understand that it won't just be the JSON that is returned from the API, and has a bunch of other internal methods etc. But when I get the data out, I can see it buried somewhere in the debugging with console.log, but I can't seem to get it into $scope to use it in my view which was working fine previously.
How can I get that data out into my $scope, and therefore my view?
Model
angular.module('horse', ['restangular'])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://url/api');
RestangularProvider.setResponseInterceptor(
function(data, operation, what) {
if (operation == 'getList') {
return data[what];
}
return data;
});
});
Controller
angular
.module('horse')
.controller("IndexController", function ($scope, Restangular) {
$scope.horse = null;
$scope.showSpinner = true;
Restangular.all('horse').getList().then(function(horse) {
$scope.horse = horse;
console.log($scope.horse);
});
});
API response
{"error":false,"horse":[{"id":"1","name":"horse 2"},{"id":"2","name":"horse 2"}]}
Edit 1
Restangular response
[Object, Object, route: "horse", getRestangularUrl: function, getRequestedUrl: function, addRestangularMethod: function, clone: function…]
Edit 2
I have also tried this - https://github.com/mgonto/restangular#using-values-directly-in-templates
$scope.horse = Restangular.all('horse').getList().$object;
Which just results in an empty array being output. I have also tried removing the setResponseInterceptor and modifying the structure of the api to result the data array directly without the meta stuff (error, etc), no joy :(
The data seems to be coming through. I notice you're using Steroids, have you checked the markup and not just the console?
Make sure you set the scope spinner to false, to ensure that the spinner is hidden when the data comes through.
$scope.ShowSpinner = false;
Assuming that what you have shown as "API response" is what's getting outputted from the console.log in your controller, it seems that all you need to do is set your scope model the the property "horse" in the response data like this:
$scope.horse = horse.horse;
Since that reads pretty oddly, you should change the param name of the .then callback to data, which would be a much more agnostic and standard param name. If you make that change you can set your horse data to your scope model from inside your callback like this:
$scope.horse = data.horse;
If I misunderstood your question let me know. Hope this is helpful.
I'm using Fine Uploader to upload files directly to Amazon S3 (not relevant to the issue).
What I'm doing is to generate an "attachment" backbone.js model (which generates an unique ID), and passing that ID to the uploader via setParams in the submit event, in order for me to identify the attachment in the complete event and take appropriate actions.
The problem is manifesting when uploading multiple files at the same time (tried with 10 files). Fine Uploader apparently calls the submit callback too fast, and I am getting duplicate model IDs in the complete event.
If I add breakpoints to the submit event and do nothing, just hit "play" again, the concurrency problem is no longer present.
Part of my code is:
var self = this;
this.uploader.on('submit', function() {
var attachment = new Market.InboxPage.Models.Attachment(); // generates a new model with a unique ID
self.attachments[attachment.cid] = attachment; // self.attachments is a model collection
self.uploader.setParams({'cid': attachment.cid});
});
this.uploader.on('complete', function(event, id, file, response) {
self.attachments[response.metadata.cid].set({ // getting duplicate data here
filename: response.metadata.qqfilename,
key: response.metadata.key,
filesize: response.metadata.filesize
});
self.attachments[response.metadata.cid].updateInDom();
return false;
});
The issue is with your calls to setParams. You are effectively overwriting the params for all existing files with each call to setParams. Instead, you should be targeting a specific file with each call to setParams. setParams allows you to do this by specifying a file ID as a parameter to the setParams call. For example:
this.uploader.on('submitted', function(event, id, name) {
var attachment = new Market.InboxPage.Models.Attachment(); // generates a new model with a unique ID
self.attachments[attachment.cid] = attachment; // self.attachments is a model collection
self.uploader.setParams({'cid': attachment.cid}, id); });
Notice how I switched your logic to the submitted event, which is called after the file has been successfully submitted, and an ID is available.
I have a grid what update my database (via PHP) with JSON record.
I want to know, how the data writed - record or not. I have an answer from PHP (true or false) to the grid, but dont know how to use it. How my grid can use this answer? (success event?)
Now, for example, User added new record without id at database (and i need this id for the future update), php answer what record saved(true) and told me id of new record. How I should work with it?
And I saw somehere some beauty flowing from the top of screen windows - how do the called?
Sorry for typically questions, but I cant find answer for it.
Thanks.
If you are using Ext.Ajax.request to make the connection this is how you do it.
Ext.Ajax.request({
url: 'ajax_demo/sample.json',
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
console.dir(obj);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
There is a success callback function you specify which gets the response from the server which is a JSON object. This is where you can send things back and then manipulate your roweditor grid however you like.
Success also doesn't mean that everything went ok, it just means the request did not produce an html error code 4xx or 5xx.
The failure callback function is what to do if the server returns an error code for the AJAX request.