I am very new to Ionic Framework. I am learning the framework and have tried to build a simple android app, which displays a simple list using json. Now, I want add a favorite list which will show user selected items in it. When user clicks on a button it should add that item in a favorite list. And When user click on Favorite tab it should show list of all favorite items.
At present I am trying to do this with simple json and global controller. But I am afraid if this is used on android app on a phone it will not store all favorites, it would remove all favourites once app is closed. Can anyone please suggest a better approach towards it.
Many thanks in advance.
I see you tagged the question with local storage, so why not use that? Also, you could use one of the popular mBaaS solutions like Firebase or gunDB.
As for the logic, it's quite easy: you create a new array which you use for storing these favorites (you handle the adding/removing on the favorite button click). You then use the ng-repeat on the Favorites tab to list the favorites array.
The best way to do this would be pouchdb, i m using in same way.!
Install pouchdb using command:
bower install pouchdb
add below line in index.html
<script src="lib/pouchdb/dist/pouchdb.min.js"></script>
make a service:
.factory('FavService', function (UserService) {
var FavService = {};
var localDB;
var user = UserService.getUser();
if (user) {
localDB = new PouchDB('u_' + user.id);
}
FavService.configDbs = function () {
//console.log('config dbs');
var user = UserService.getUser();
if (user) {
localDB = new PouchDB('u_' + user.id);
}
};
FavService.storeToLocal = function (product) { //change function name
if (localDB && product !== "") {
localDB.post(product);
// console.log("Action completed");
} else {
// console.log("Action not completed");
}
};
FavService.getLocalList = function (callback) {
if (localDB) {
localDB.allDocs({
include_docs: true
}).then(function (response) {
// console.log("response :"+JSON.stringify(response));
localDB = response.rows;
callback(response.rows);
}).catch(function () {
callback(null);
});
} else {
FavService.configDbs();
}
};
});
Related
I am building a fitness website on Wix. What I have is a database collection of all the training videos. When someone purchases a plan the trainer needs to have their own "Trainer Portal" where they can build the plan for the customer. I need the trainer to be able to filter through the database collection videos and then click "ADD". When they click "ADD" it pushes that video to a data collection then on the same page populate a repeater. The filtering videos I have done with no problem, the problem I am facing is pushing the videos from one database to another database within the webpage. I can only push the information about the video to another data collection but not the actual video.
If anyone knows if this is possible then please point me in the right direction.
Here is my code below.
// For full API documentation, including code examples, visit https://wix.to/94BuAAs
import wixData from "wix-data";
let debounceTimer;
export function iTitle_keyPress(event, $w) {
if (debounceTimer) {
clearTimeout(debounceTimer)
debounceTimer = undefined;
}
debounceTimer = setTimeout(() => {
filterTitle($w('#iTitle').value);
}, 200)
// Add your code for this event here:
}
function filterTitle(title) {
console.log($w('#iTitle').value);
$w('#allVideosDatatSet').setFilter(wixData.filter().contains('title', title))
}
export function addVideos(event) {
let toInsert = {
"video1": $w("#videoPlayer1")
}
wixData.insert("Week1", toInsert)
$w("#week1Dataset").save()
.then( (results) => {
let item = results;
console.log("Your video was saved!!!!");
})
.catch( (error) => {
let logErrorMessage = error;
// console.log(error);
} );
}
3 things
First: I'm assuming you have a button with the id of addVideos hence the export function
Your function export function addVideos(event) {} may not be correct, it should be added via the Properties Panel and should read something like export function addVideos_click(event) {} or add it under the page's onReady function like this:
$w("#addVideos").onClick( (event) => {
//put code here
});
Second: You should scope an item if your button is inside a repeater. Read my answer here to understand more about scoping an item from a repeater.
Third: If the button is inside the repeater then your code should look like below:
export function addVideos(event) {
let $item = $w.at(event.context);
let toInsert = {
"video1": $item("#videoPlayer1").src //Missing the .src to get the video source link & also assuming video player is inside the repeater
};
wixData.insert("Week1", toInsert) //"Week1" should be the database id
.then( (results) => {
console.log("Your video was saved!!!!");
})
.catch( (error) => {
console.log(error);
});
}
Regarding this: "I can only push the information about the video to another data collection but not the actual video"
Videos are stored in the Wix Media Manager, the wix database only stores the link to the video which may begin like wix://video so you cannot "move a video" between databases, just the link which you can get via .src if you want the link of a video player.
I am trying to implemented ionic push from ionic.io.
Sending push to all users are working, but sending push to a specific user is not working.
The codes for ionic push are following as below:
function IonicPushInit(){
var push = new Ionic.Push();
var callback = function(token) {
push.saveToken(token);
}
push.register(callback);
}
function IonicIoLogin(){
var user = Ionic.User.current();
if (user.isAuthenticated()) {
IonicPushInit();
} else {
var details = {
'email': 'asdsadsads#mail.com',
'password': 'secretpassword'
};
var options = { 'remember': true };
Ionic.Auth.login('basic', options, details).then(function(sucRes){
IonicPushInit();
}, function(err){
Ionic.Auth.signup(details).then(function(s){
IonicPushInit();
}, function(e){
alert(e);
});
});
}
}
IonicIoLogin();
After execute above codes, when I send a push to all users from ionic.io, it works. But if I send a push to a specific user with following condition, it doesn't work.
So I've checked the user "asd...#mail.com" in User Tab, but in ther the push tab is empty. Is this the reason? Why it is empty?
What's wrong with above the codes?
Your code seems good, so it has to be something with project configuration.
Did you follow ionic documentation to use "Full setup"? Assign tokens to real users does not work on "Limited setup" => http://docs.ionic.io/docs/push-full-setup
After follow steps of "Full setup" I had your problem.
Then I realized that register doesn't work in browser or emulator. You have to try it on real device.
To have more information about your register function, just use:
var push = new Ionic.Push({"debug": true});
i am very new to pouchdb, meaning i have not yet been successfully able to implement an app that uses it.
This is my issue now, in my controller i have two functions:
var init = function() {
vm.getInvoicesRemote(); // Get Data from server and update pouchDB
vm.getInvoicesLocal(); // Get Data from pouchDB and load in view
}
init();
Basically in my app i have a view that shows customer invoices, now i want customers to be able to still see those invoices when they're offline. I have seen several examples of pouchdb and couchdb but all use the "todo" example which does not really give much information.
Now i'm just confused about what the point was in me spending hours understanding couchdb and installing it if in the end i'm just going to be retrieving the data from my server using my API.
Also when the data is returned how does pouchdb identify which records are new and which records are old when appending.
well, i m working on same kind..!this is how i m making it work..!
$scope.Lists = function () {
if(!$rootScope.connectionFlag){
OfflineService.getLocalOrdersList(function (localList) {
if(localList.length > 0) {
$scope.List = localList;
}
});
}else{
if(!$scope.user){
}else {
Common.callAPI("post", '***/*************', $scope.listParams, function (data) {
if (data !== null) {
$scope.List = data.result;
OfflineService.bulkOrdersAdd_updateLocalDB($scope.List);
}
});
}
}
};
so,$scope.List will be filled if online as well as offline based on connectionFlag
note : OfflineService and Common are services.
call method:
$ionicPlatform.ready(function () {
OfflineService.configDbsCallback(function(res) {
if(res) {
$scope.Lists();
}
});
});
u can try calling $scope.Lists(); directly..!
hope this helps u..!
I've configured all users to be created with an empty favorites array: user.favorites: []
Since the users collection is treated differently, how should I publish, subscribe, and access subscribed favorites data in angular-meteor?
Here's what I have so far:
// Meteor.methods ==========================================
addFavorite: function(attendeeId){
var loggedInUser = Meteor.user();
if( !loggedInUser ){
throw new Meteor.Error("must be logged in");
}
loggedInUser.favorites.push(attendeeId);
loggedInUser.username = loggedInUser.username+"x";
console.log(loggedInUser.favorites);
}
// controller ========================================
$scope.addFavorite = function(attendeeId){
$meteor.call("addFavorite", attendeeId);
}
// server =======================================================
Meteor.publish('myFavorites', function(){
if(!this.userId) return null;
return Meteor.users.find(this.userId);
});
Meteor.users.allow({
insert: function(userId, doc){
return true;
},
update: function(useId, doc, fieldNames, modifier){
return true;
},
remove: function(userId, doc){
return true;
}
});
User.favorites is empty. When addFavorite is called, it logs an array with a single userId that doesn't update the mongoDB at all. It looks as if Meteor.user() isn't reactivly updating. Does anyone know what I'm doing wrong? Thank you!
EDIT
Latest iteration of code. Favorites are passed into $scope.favorites but isn't reactive. How do I fix this? Thanks!
// publish
Meteor.publish('myFavorites', function(){
if(this.userId){
return Meteor.users.find(this.userId, {
fields: {
favorites: 1
}
});
}else{
this.ready();
}
});
// subscribe
$meteor.subscribe('myFavorites')
.then(function(subscriptionHandle)
{
var user = $meteor.collection(function(){
return Meteor.users.find({_id: Meteor.userId()});
});
$scope.favorites = user[0].favorites;
});
tldr;
Accounts collection is reactive, but by default only the username, emails, and profile fields are published. The quickest fix is to attach the favorites as a new field on the User.profile object.
// Meteor.methods ==========================================
addFavorite: function(attendeeId){
var loggedInUser = Meteor.user();
if( !loggedInUser ){
throw new Meteor.Error("must be logged in");
}
if (loggedInUser.profile.favorites){
loggedInUser.profile.favorites.push(attendeeId);
}
else {
loggedInUser.profile.favorites = [];
loggedInUser.profile.favorites.push(attendeeId);
}
loggedInUser.username = loggedInUser.username+"x";
console.log(loggedInUser.profile.favorites);
}
Although right now you probably are writing to the user, which you can verify by using meteor mongo --> db.users.find().pretty(), but the subscription does not publish your favorites field.
Alternative approach
Alternatively, you can publish the favorites field
// Server code --------
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'favorites': 1}});
} else {
this.ready();
}
});
Opinionated Meteor.users philosophy
I like to structure my users object around 3 properties:
User.profile --> published to the client, and directly modifiable by the client through client-side code
User.public --> published to the client, but not modifiable except through server-side Meteor methods
User.private --> not published to the client (i.e. only accessible to read on server code), and only modifiable by server code (with client simulation)
Just make sure that when you remove the insecure and autopublish packages that you double-check your Collections security by using the Meteor.users.allow() function in your server code
Run meteor list to if you want to verify whether or not insecure and autopublish packages are being used in your current project. NOTE: By default Meteor does install them when you first create your app)
// Server code --------
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'public': 1}});
} else {
this.ready();
}
});
I am trying to build an Angular project with Pusher using the angular-pusher wrapper. It's working well but I need to detect when the user loses internet briefly so that they can retrieve missed changes to data from my server.
It looks like the way to handle this is to reload the data on Pusher.connection.state('connected'...) but this does not seem to work with angular-pusher - I am receiving "Pusher.connection" is undefined.
Here is my code:
angular.module('respondersapp', ['doowb.angular-pusher']).
config(['PusherServiceProvider',
function(PusherServiceProvider) {
PusherServiceProvider
.setToken('Foooooooo')
.setOptions({});
}
]);
var ResponderController = function($scope, $http, Pusher) {
$scope.responders = [];
Pusher.subscribe('responders', 'status', function (item) {
// an item was updated. find it in our list and update it.
var found = false;
for (var i = 0; i < $scope.responders.length; i++) {
if ($scope.responders[i].id === item.id) {
found = true;
$scope.responders[i] = item;
break;
}
}
if (!found) {
$scope.responders.push(item);
}
});
Pusher.subscribe('responders', 'unavail', function(item) {
$scope.responders.splice($scope.responders.indexOf(item), 1);
});
var retrieveResponders = function () {
// get a list of responders from the api located at '/api/responders'
console.log('getting responders');
$http.get('/app/dashboard/avail-responders')
.success(function (responders) {
$scope.responders = responders;
});
};
$scope.updateItem = function (item) {
console.log('updating item');
$http.post('/api/responders', item);
};
// load the responders
retrieveResponders();
};
Under this setup how would I go about monitoring connection state? I'm basically trying to replicate the Firebase "catch up" functionality for spotty connections, Firebase was not working overall for me, too confusing trying to manage multiple data sets (not looking to replace back-end at all).
Thanks!
It looks like the Pusher dependency only exposes subscribe and unsubscribe. See:
https://github.com/doowb/angular-pusher/blob/gh-pages/angular-pusher.js#L86
However, if you access the PusherService you get access to the Pusher instance (the one provided by the Pusher JS library) using PusherService.then. See:
https://github.com/doowb/angular-pusher/blob/gh-pages/angular-pusher.js#L91
I'm not sure why the PusherService provides a level of abstraction and why it doesn't just return the pusher instance. It's probably so that it can add some of the Angular specific functionality ($rootScope.$broadcast and $rootScope.$digest).
Maybe you can set the PusherService as a dependency and access the pusher instance using the following?
PusherService.then(function (pusher) {
var state = pusher.connection.state;
});
To clarify #leggetters answer, you might do something like:
app.controller("MyController", function(PusherService) {
PusherService.then(function(pusher) {
pusher.connection.bind("state_change", function(states) {
console.log("Pusher's state changed from %o to %o", states.previous, states.current);
});
});
});
Also note that pusher-js (which angular-pusher uses) has activityTimeout and pongTimeout configuration to tweak the connection state detection.
From my limited experiments, connection states can't be relied on. With the default values, you can go offline for many seconds and then back online without them being any the wiser.
Even if you lower the configuration values, someone could probably drop offline for just a millisecond and miss a message if they're unlucky.