I'm trying to understand the correct workflow to create a $setPristine equivalent with my Firebase data.
My workflow is as follows:
1) Create Firebase object (via the Angularfire Generator 'SyncData')
2) Form data modifies the $firebase object.
3) To update the remote model, I use myRef.$save()
All of that works well. Now, I'm trying to add a "reset" button on the form, so that the locally modified data will revert back to the remotely stored data.
So far, I'm running into problems. I've tried reinitializing the firebase reference eg myRef = syncData('/my/path') but not only does that now work, but it is destroying the remote data object!
What is the correct way to re-pull the remote data to use in my Angular model?
I know this is an old question, but I ran into this issue myself.
After some searching around I found this post: http://grokbase.com/t/gg/firebase-angular/1499haaq4j/editing-data-as-a-copy
Which led me to an outdated code snippet (2 months lol XD) from #Kato: https://gist.github.com/katowulf/8eaa39eab05a4d975cd9
I modified this to work with Firebase 2.3.1 and AngularFire 1.1.3:
app.factory('ResetFactory', function($firebaseArray) {
return $firebaseArray.$extend({
reset: function(itemOrIndex) {
var key, self;
self = this;
key = self.$keyAt(itemOrIndex);
self.$ref().child(key).once('value', function(snap) {
self.$$updated(snap);
});
}
});
});
Which can be called via:
var comments = new RevertFactory(ref.child('comments'));
# variable comment is for example an ng-repeat that's being edited
comments.reset(comment);
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'm using LokiJS to save in local storage (well, I'm trying) .
What I want to do is a ToDo app, my controller is as follows:
.controller('Dash', function($scope) {
var db = new loki('loki.json');
$scope.name="";
$scope.lname="";
var users=db.getCollection('users');
if (users==null) {
$scope.message="It's null";
var users = db.addCollection('users');
}else{
$scope.message="It's ready";
}
$scope.insert=function(namesI, lnameI){
users.insert({
name: namesI,
lname:lnameI
});
}
The issue is that everytime that I test it, the message is "It's null". Although before already I have inserted data. I mean, everytime I launch the app, the database is created.
How I can persist the data?
*I'm not using any cordova plugin.
You are not providing a loadHandler function, so you are trying to access collections before Loki is finished loading the json file. Look at this example for a clarification on how to use the autoLoadHandler.
Also bear in mind that at some stage you need to call db.saveDatabase() to persist, or else you need to provide an autoSaveInterval value when instantiating Loki.
I am trying to create a 'Favorites' section in my app where you hit a button and it is added to a user favorites list in firebase. I am using the ionic platform.
I created a factory to handle the favourites as they come in. and i use the getAuth() function to get the unique userID so i can just pull it when the user logs on. This is my attempt but i am not getting the result i wanted which is simply something like :
< userid >:
{
0: "fav1"
1: "fav2"
}
.factory('Favourites',function($firebaseArray){
var ref = new Firebase("https://experiencett.firebaseio.com/");
var authData = ref.getAuth();
var favs = $firebaseArray(new Firebase('https://experiencett.firebaseio.com/favourites/'+authData.uid+''));
return {
all: function() {
return favs;
},
add: function(){
var up=new Firebase('https://experiencett.firebaseio.com/favourites/');
var usersref=up.child(authData.uid);
usersref.push({3:"paria"});
},
When you call push() you are generating a unique id. While that is great for many use-cases, it is not good here since you want to control the path that is written.
Since you're already constructing the path with child(authData.uid) you can simply update it with update():
usersref.child(authData.uid).update({3: "paria"});
This will either update the existing value at 3 or write the new value for 3, leaving all other keys under /users/<uid> unmodified.
Alternatively if you want to replace the data that already exists at users/<users>, you can use set() instead of update().
This is all covered in the Firebase JavaScript SDK in the section on storing user data. It is not covered in the AngularFire documentation, since there is nothing specific to Angular about it.
I have the following publisher and subscriber code.
It works for the first time when the app starts, but when I try to insert data directly into the Mongo database, it will not automatically update the user screen or I don't see the alert popping.
Am I missing something?
Publish
Meteor.publish('userConnections', function(){
if(!this.userId){
return;
}
return Connections.find({userId: this.userId});
})
Subscribe
$scope.$meteorSubscribe('userConnections').then(function () {
var userContacts = $scope.$meteorCollection(Connections);
alert("subscriber userConnections is called");
if (userContacts && userContacts[0]) {
....
}
}, false);
First off, if you are not using angular-meteor 1.3 you should be. The API has changed a lot. $meteorSubscribe has been deprecated!
To directly answer your question, $meteorSubscribe is a promise that gets resolved (only once) when the subscription is ready. So, it will only ever be called once. If you look at the documentation for subscribe you'll see how to make the binding "reactive", by assigning it to a scope variable. In your case it would be something like:
$scope.userContacts = $scope.$meteorCollection(Connections);
Doing it this way, when the collection gets updated, the $scope.userContacts should get updated as well.
UPDATE : find my answer here
A little clarity on getting key values using AngularFire v2?
I looked for many sources before asking a simple question but Im just sarting with firebase and I can't manage to use the data the way I want. What I need, is to retrieve two int in my controller (how much "yes" and how much "no" linked to a question.
the data model is the following
question/id/(text, yes, no)
I have a service where I call my data using an id
app.service('QuestionService', function($firebase,$q) {
var _this = this;
//initialize Firebase
var ref = new Firebase('https://basename.firebaseio.com/question');
this.get = function(nb){
var QuestionObject = ref.child(nb);
return $firebase(QuestionObject);
};
return this;
});
I have a controller function where I call some data using a random id
$scope.pickQuestion = function(){
var randomnumber = Math.ceil(Math.random() * 3);
$scope.message = QuestionService.get(randomnumber);
};
and then it works great so I can have something like
{{message.yes}} or {{message.no}} and get the corresponding integer.
My issue, what I want to do, is to pass this "message.no" value to my controller. I don't know what to do. I can't manage to get the value directly inside the controller (it works only inside the view) and I can't manage to pass the value to my controller from the view. I tried a
ng-init="functionName({{message.yes}}, {{message.no}})"
but it return an error into the console. (however the source a displayed correctly)
Does someone could guide me into the right direction?
Thanks