Meteor Collection find()/fetch() working sometimes - angularjs

I started working with meteor which seems to be good for my use, a problem occurred where I get my documents only 9/10 times. I think I implemented something wrong.
I use Angular 1.5 and Typescript
My collection gets created in the lib folder at /
import { Mongo } from 'meteor/mongo';
export const Locations= new Mongo.Collection('locations');
then the collection gets imported to my service
import {app} from '../../js/lib/app';
import {Locations} from '../../../lib/collections';
export class LocationsService {
locations: any;
constructor(){
console.log('Constructor called');
this.locations = Locations
.find({})
.fetch();
console.log('documents loaded');
console.log(this.locations);
}
public createLocation(any:any){
Locations.insert(any);
}
public updateLocation(identity:any, modifier:any){
Locations.update(identity,modifier);
}
}
app.service('locationsService', LocationsService);
Here are the console.logs from 3 different page refreshes:
It looks like the amount of docs I get is totally random.

Here is some code that will help you. It uses the "resolve" feature of ui-router to hold up loading of the page until data is loaded. In this case there are two things being resolved:
User record
Elders record
The second one needs an "elderid" from users.profile in order to find an elder record.
function config($locationProvider, $urlRouterProvider, $stateProvider) {
'ngInject';
$stateProvider
.state('member.calendar', {
url: '/calendar',
template: "<membercalendar></membercalendar>",
resolve: {
currentUser: ($q) => {
var deferred = $q.defer();
Meteor.autorun(function () {
if (!Meteor.loggingIn()) {
if (Meteor.user() == null) {
deferred.reject('AUTH_REQUIRED');
} else {
deferred.resolve(Meteor.user());
}
}
});
return deferred.promise;
},
elder: ($q) => {
var deferred = $q.defer();
Meteor.autorun(function () {
if (!Meteor.loggingIn()) {
if (Meteor.user() == null) {
deferred.reject('AUTH_REQUIRED');
} else {
deferred.resolve(Elders.find({_id: Meteor.user().profile.elderid}));
}
}
});
return deferred.promise;
}
}
});
}
This works well if you want the data to be loaded fully before the page loads. If you don't mind an asynchronous update to the page, you can use getReactively to make a helper run once the data has resolved. I can give you example code for that too if you like.

My new Service simply subscribes
export class LocationsService {
locations:any;
constructor(){
console.log('Constructor called');
//Subscribe to a collection//localStorage.getItem('ID')
Meteor.subscribe('locations', 2223 );
this.locations = Locations;
console.log('documents loaded');
}
public createLocation(any:any){
Locations.insert(any);
}
public updateLocation(identity:any, modifier:any){
Locations.update(identity,modifier);
}
}
app.service('locationsService', LocationsService);
In my controller i simply add the fetching of my documents in the Tracker.
import {app} from '../../js/lib/app';
import {LocationsService} from './LocationsService';
import {Tracker} from 'meteor/tracker';
export class LocationsController {
static $inject = ['locationsService','$reactive','$scope'];
public $reactive: any;
public $scope: any;
public locations: any[];
constructor(private locationsService: LocationsService, $reactive:any, $scope:any){
this.locationsService = locationsService;
this.$reactive = $reactive;
this.$scope = $scope;
$reactive(this).attach(this.$scope);
Tracker.autorun(() => {
//console.log('autorun');
this.locations = locationsService.locations.find({}).fetch();
console.log(this.locations)
});
}
public createLocation(location:any){
console.log('Locations does what it should');
console.log(location);
this.locationsService.createLocation(location);
}
public updateLocation(location:any, modifier:any){
this.locationsService.updateLocation(location._id,modifier)
}
}
app.controller('locationsController', LocationsController);
The only problem I have now is that the modell updates like a charm but not the view when I create new locations. The autorun works and the new location gets saved in my collection but I see it only if I reload. But that one is low priority for me.

Related

Share Data between Services in angular js 1.4

Sample URLs:
/users/api/getUser
/users/api/addUser
/users/api/deleteUser/{userId}
I want to store the common path(/users/api) in a global variable and pass it to each service so as to concate it with Request URL before calling REST endpoint. I have created one class and stored url prefix. But I am not able to get its value in Service. Below is the code snippet.
import CommonVariables from './commonVariables';
class UserService {
/*#ngInject*/
constructor($rootScope, Rest){
Object.assign(this, {$rootScope, Rest});
}
getUsers() {
console.log("commonVariables.getBaseURL: ", CommonVariables.baseURL);
console.log("commonVariables.getBaseURL: ", CommonVariables.getBaseURL());
return this.Rest.one("/users/api/getUser").get();
}
addUserDetails(request) {
return this.Rest.one("/users/api/addUser").customPOST(request);
}
}
export default UserService
CommonVariable
class CommonVariables {
/*#ngInject*/
constructor($rootScope){
Object.assign(this, {$rootScope});
let vm = this;
vm.baseURL = "/users/api";
}
getBaseURL() {
console.log("getBaseURL called");
return "/users/api";
}
}
export default CommonVariables
Change export default CommonVariables to export default new CommonVariables();

Nativescript Angular ActivityIndicator

in my Nativescript Angular app i am using an ActivityIndicator, setup as i've seen in the Nativescript Angular docs (the GroceryList example):
<ActivityIndicator width="30" height="30" [busy]="refreshing" [visibility]="refreshing ? 'visible' : 'collapsed'" horizontalAlignment="center" verticalAlignment="center"></ActivityIndicator>
if the Component using it i have:
export class MyComponent {
public refreshing = false;
........
}
Then i fetch some data from my backend:
public onRefreshTap() {
console.log("onrefreshtap");
this.refreshing = true;
this.backend.getData(function (data) { //this.backend is my Service
this.refreshing = false;
})
}
The problem is that when i put this.refreshing to true, the ActivityIndicator correctly shows. But when bakend request completes (and so, i put this.refreshing=false) the ActivityIndicator does not hides... (and also it seems that its busy property is not updated, it stays in spinning state)..
What am i doing wrong ?
Thanks in advance
You could also try to access the refreshing property as it has been shown in the sample codes below. It could be a problem of accessing the property inside the callback method of your service.
public onRefreshTap() {
var that = this;
this.refreshing = true;
this.backend.getData(function (data) { //this.backend is my Service
that.refreshing = false;
})
}
or
public onRefreshTap() {
this.refreshing = true;
this.backend.getData((data) => {
that.refreshing = false;
})
}
It may be many things:
1) The change to false, on the Observable, is not being "seen" by the component.
------ The solution is run the code in a Zone (see https://angular.io/docs/ts/latest/api/core/index/NgZone-class.html )
2) The backend is returning an error (I don't see it dealing with that in the code).
------ The solution is put a function to deal with the error.
3) The callback is not being called. In your code, you're SENDING a function as a parameter to the backendService, so maybe the service is not executing it.
------ Try using a Promisses or Observables to deal with returned values (you'll have to Google about it, since I'm still learning them my explanation would be the worst). :)
Here's some code that might work:
my-component.html
<ActivityIndicator [busy]="isWorking" [visibility]="isWorking?'visible':'collapse'"></ActivityIndicator>
my-component.ts
import { Component, NgZone } from "#angular/core";
...
export class MyComponent {
isWorking:boolean = false;
constructor(private backendService: BackendService,
private _ngZone: NgZone)
{
this.isWorking = false;
}
public onRefreshTap() {
console.log("onrefreshtap");
this.isWorking = true;
this.backendService.getData()
.then(
// data is what your BackendService returned after some seconds
(data) => {
this._ngZone.run(
() => {
this.isWorking = false;
// I use to return null when some Server Error occured, but there are smarter ways to deal with that
if (!data || data == null || typeof(data)!=='undefined') return;
// here you deal with your data
}
)
}
);
}
}

Angular 2 TS object array only defined while subscribed to service

I'm in the process of learning Angular 2 using TypeScript. So far I've written a little API service that uses HTTP get method to feed me json data using observables. Everything is working fine, I can use the data in my view, I can also use the data in my component, but only while I'm subscribed to the getData() method.
Why is that and what other possibilities do I have to make the object array available to all methods in my component for easy iteration and management?
Example component:
export class SomeComponent implements OnInit {
public someData: DataObject[];
public constructor(private service: SomeService) {}
public ngOnInit(): void {
this.loadData();
this.useData();
}
private loadData(): void {
this.service.getData().subscribe(data=> {
this.someData = data;
this.someData.forEach(dataObject => {
// this works fine
});
});
}
private useData(): void {
this.someData.forEach(dataObject => {
// dataObject is (of type?) undefined, why?
});
}
}
It's because http calls are async. Your this.useData(); does not wait this.loadData(); to finish. This should work:
private loadData(): void {
this.service.getData().subscribe(data=> {
this.someData = data;
this.useData();
});
}

Angular 2 / Ionic 2 — Correct way to Build Array of Observables that http.get Data on Interval

I'm working with Angular 2 and Ionic 2, trying to build an array of reactive objects.
I'm trying to figure out the correct way to build an ion-list component (StocksList) that populates itself via a simple service (StocksListService) that instantiates new observable (Stock) class instances which get their data from a service (StockService) that calls an API repeatedly on an Observable.interval.
Ultimately I want to be able to create a stateful pipe to sort the Stocks[] (and I want to understand the actual correct way to do what I'm doing).
I don't really know how to explain my intention concisely any better than that, so I'm hoping my code will help clarify the situation:
——
Home Page
^
Stocks List Component < Stocks List Service
^
Stock Component < Stock Service
——
Home Page—
home.html
<ion-content>
<ion-list
stocksListCmp ></ion-list>
</ion-content>
home.ts
#Page({
templateUrl: 'build/pages/home/home.html',
directives: [StocksList],
providers: [StocksListService]
})
export class HomePage {
constructor(public nav: NavController) { }
}
Stocks List Component—
stocks-list.tpl.html
<ion-card
[stockCmp]="stock"
*ngFor="#stock of stocks; #i = index"></ion-card>
stocks-list.component.ts
#Component({
selector: '[stocksListCmp]',
viewProviders: [StocksListService, StockService]
})
#View({
templateUrl: 'build/components/stocks-list/stocks-list.tpl.html',
directives: [Stock]
})
export class StocksList {
stocks: Observable<IStock>[]; // not sure if my typing is correct here, or anywhere with advanced types really
constructor(private stocksListService: StocksListService) { }
ngOnInit() {
this.stocks = this.stocksListService.stocks;
}
}
stocks-list.service.ts
let tickers: string[] = ['AAPL', 'BTCUSD=X', '^DJI', '^GSPC', 'NFLX', 'TSLA'];
#Injectable()
export class StocksListService {
constructor( #Inject(forwardRef(() => StockService)) private stockService: StockService) { }
get stocks(): Observable<IStock>[] {
return tickers
.map((ticker) => new Stock(this.stockService.init(ticker))); // getting type error on this.stockService.init(ticker): Observable<Observable<IStock>> not assignable to StockService
}
}
Stock Component—
stock.tpl.html
<ion-card-content>
<ion-row>
<ion-col>{{ stock?.ticker }}</ion-col>
<ion-col>{{ stock?.price }}</ion-col>
<ion-col>{{ stock?.chg_percent}}</ion-col>
</ion-row>
</ion-card-content>
stock.component.ts
#Component({
selector: '[stockCmp]',
inputs: ['stockCmp'],
viewProviders: [StockService]
})
#View({
templateUrl: 'build/components/stock/stock.tpl.html'
})
export class Stock {
stockCmp: Stock; // not sure how to type here
stock: IStock; // not sure how to type here
constructor(private stockService: StockService) { }
ngOnInit() {
this.stockCmp['stockService']['init']
.subscribe((data) => this.stock = data,
null,
() =>
this.stockCmp['stockService']['update']
.subscribe((service) => service
.subscribe((data) => this.stock = data))
);
}
}
stock.service.ts
let source: Observable<number> = Observable.interval(60 * 1000).publish().refCount();
#Injectable()
export class StockService {
constructor(private http: Http) { }
public init(ticker: string): Observable<Observable<IStock>> {
if (ticker) {
let url = 'http://finance.yahoo.com/webservice/v1/symbols/' + ticker + '/quote?format=json&view=detail';
return this.updateData(url);
}
}
private loadData(url: string): Observable<IStock> {
return this.http.get(url)
.map((res) => this.mapData(res.json().list.resources[0].resource.fields));
}
private mapData(data: any): IStock {
return {
ticker: data.symbol,
name: data.name,
price: JSON.parse(data.price),
chg_percent: JSON.parse(data.chg_percent) / 100,
ts: data.ts
};
}
public updateData(url: string): Observable<Observable<IStock>> {
return { init: this.loadData(url), update: source.map(() => this.loadData(url)) }; // type error
}
private logError(error) {
console.log(error);
}
}
stock.d.ts
export interface IStock {
ticker: string;
name: string;
price: number;
chg_percent: number;
ts: number;
}
So this actually works pretty well right now but I'm certain it's not the correct way to do it. There has to be a better way to get the results from the loadData method before the first interval call.
I'd like to understand the correct way to do this in regards to building the ion-list, instantiating new class instances, and using reactive extensions and hopefully that will help me implement a stateful pipe to sort the stocks list.
Any advice is much appreciated! If I've left anything out or need to clarify anything, please let me know. Thanks!

How to pass data from AngularJS form to struts 2 action class?

Here I am developing shopping cart. This is my AngularJS controller. This method use to send data to action
class using $http.post method
angular.module("sportsStore")
.constant("dataUrl", "angularAction")
.constant("orderUrl", "angularSaveAction")
.controller("sportsStoreCtrl", function ($scope, $http, $location,
dataUrl, orderUrl, cart) {
enter code here`$scope.data = {
};
$scope.sendOrder = function (shippingDetails) {
var order = angular.copy(shippingDetails);
order.products = cart.getProducts();
console.log(order);--------------(1)
$http.post(orderUrl, order)
.success(function (data) {
//$scope.items=data;
$scope.data.orderId = data.id;
cart.getProducts().length = 0;
console.log(data);---------------(2)
})
.error(function (error) {
$scope.data.orderError = error;
}).finally(function () {
$location.path("/complete");
});
}});
Using (1) console.log i confirm all form data and shopping cart detail stoed array.But (2) console log is Null
This is my Action class
package com.ai.action;
import com.ai.model.PersonData;
import com.ai.model.Product;
import com.ai.model.ProductOrder;
import com.ai.model.Village;
import com.ai.service.PersonService;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.slf4j.Logger;
public class OrderAction extends
ActionSupport implements ModelDriven<ProductOrder> {--------------(1)
private Map session = ActionContext.getContext().getSession();
private Logger logger = LoggerFactory.getLogger(AngularAction.class);
private List<ProductOrder> order;-------------(2)
private ProductOrder productOrder;
#Autowired
private PersonService personService;
public String execute()
{
getOrder();
logger.info("this method ic" ,order);
//personService.save(personService);----------(3)
return SUCCESS;
}
public List<ProductOrder> getOrder() {
return order;
}
public void setOrder(List<ProductOrder> order) {
this.order = order;
}
#Override
public ProductOrder getModel() {
return productOrder;
}
}
How I get form data
Can I use
ModleDriven(1) or
List array(2) or any method. I want save this form data in mysql database using hibernate(3).please help me....
How I get form data
Can I use
ModleDriven(1) or
List array(2) or any method. I want save this form data in mysql database using hibernate(3).please help me....

Resources