0

i am trying to get google maps values from parent component to route component for which i have created a sharedservice as follow

import {Injectable}     from 'angular2/core';
import {Subject} from "rxjs/Subject";
@Injectable()
export class SearchService {

    private addressmap= new Subject<Sharedcomponent >();

    public searchaddressStream$ = this.addressmap.asObservable();

    broadcastaddressChange(address: Sharedcomponent ) {
        this.addressmap.next(address);
    }
}
export class Sharedcomponent {
    country: string;
    state: string;
    city: string;  
    street: string;
}

from parent i am broadcasting this address on value change and receiving it in child by subscribing to it and its all working only if the child page is rendered with parent. if parent is rendered first then i call the child view via routing then it doesnt show the data at start when page is rendered it shows only if i change the value in parent changed again. the child view is subscribing to the service but its not getting data when rendered. If you need more explanation or code from parent or view let me know. hope someone can help me on this.

UPDATE

this is the update so you can understand my problem its my app component where i am getting values from google maps api

declare var google: any;

@Component({
    selector: 'my-app',
    templateUrl: 'app/app.component.html',
    directives: [ROUTER_DIRECTIVES, ProductComponent],
    providers: [ SearchService]
})


export class AppComponent  {

    constructor(private _http: geoService, private sharedService: SearchService, private cdr: ChangeDetectorRef) {



    }
    ngOnChanges() {
        this.sharedService.broadcastTextChange(this.street);
        this.cdr.detectChanges();
    }
    public maps: geoResult;
    public cat_error: Boolean = false;
    public xml_Latitude :any;
    public xml_Lang: any;
    public city: string;
    public state: string;
    public coutnry: string;
   public street= new SharedService;
    public input: any;
    public autocomplete: any;

    ngOnInit() {
       var instance = this,
       autocomplete;
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(res=> {
                instance._http.getPlaces(res.coords.latitude, res.coords.longitude).subscribe(
                    data=> {
                        instance.maps = data;
                        console.log(instance.maps);
                        var result = instance.maps.status;
                        var result2 = instance.maps.results;
                        if (result != "undefined" || "" || null) {

                            instance.setValue(result2[0].address_components[6].long_name, result2[0].address_components[5].long_name, result2[0].address_components[4].long_name);
                        }

                    });
            });
        }
        instance.input = document.getElementById('google_places_ac');
        autocomplete = new google.maps.places.Autocomplete(instance.input, { types: ['(cities)']});
        google.maps.event.addListener(autocomplete, 'place_changed', function () {
            var place = autocomplete.getPlace(); console.log(place);
            if (place.address_components[3] != undefined ) {
                instance.setValue(place.address_components[3].long_name, place.address_components[2].long_name, place.address_components[1].long_name);
            } else
            {
                instance.setValue(place.address_components[2].long_name, place.address_components[1].long_name, place.address_components[0].long_name);
            }
        });



    }


    setValue(a, b, c) {

        this.street.country = a;
        this.street.state = b;
        this.street.city = c;
        this.sharedService.broadcastTextChange(this.street);

    }


}

later i have a child view which gets this value

  ngOnInit() {


        this.getNewProduct();
        this.getlocation();


   }
    getlocation() {
        this.shared.searchTextStream$.subscribe(
            text => {
                this.street = text;
                this.country = this.street.country;
                this.state = this.street.state;
                this.city = this.street.city
                console.log(this.country, this.state, this.city);
            }, error=> { console.log(<any>error);}
        );
    }



    getNewProduct() {

        this._productService.selectproduct(0)
            .subscribe(
            product  => {
                this.model = product;

                this.isloading = false;
            console.log(this.model)
            },
            error => this.errorMessage = <any>error);

    }

}

but i am not getting geolocation on when this view is rendered and if i change value in parent's text box then its gets updated in view

Ironsun
  • 801
  • 2
  • 8
  • 19
  • View is not getting updated issue? – micronyks Apr 04 '16 at 09:56
  • How does the component added by the router look like? – Günter Zöchbauer Apr 04 '16 at 09:56
  • @micronyks yes you can say view is not updated on call but as soon as i am changing the value in parent textbox it reflects on view – Ironsun Apr 04 '16 at 10:06
  • @GünterZöchbauerits same you can refer this question http://stackoverflow.com/questions/36387480/value-not-updating-in-the-view-after-data-update-angular2-and-typescript/36387524?noredirect=1#comment60393355_36387524 – Ironsun Apr 04 '16 at 10:07
  • This other question also doesn't seem to provide much information. – Günter Zöchbauer Apr 04 '16 at 10:15
  • I really don't understand what is the real problem. yesterday I advised you for two things, `1. changeDetection, 2 shardObject`. Otherwise, you code is not enough to understand your problem. – micronyks Apr 04 '16 at 10:18
  • @micronyks changedetection not working when view is called it works later and how to use sharedobject? and what is ngZone can i use it in this case? – Ironsun Apr 04 '16 at 10:33
  • Looks like the answer below is correct. – Günter Zöchbauer Apr 04 '16 at 10:34
  • @GünterZöchbauer which answer? behavioursubject i am not finiding any good documents – Ironsun Apr 04 '16 at 11:17
  • 1
    Yes, `BehaviorSubject`, it returns the most recently emitted value immediately to a new subscriber. This way when a subscriber subscribes **after** an event was emitted, it still gets the last value passed. https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/behaviorsubject.md – Günter Zöchbauer Apr 04 '16 at 11:19

2 Answers2

1

If you want to listen to the last broadcast, even if you were not subscribed yet then you need to use BehaviorSubject instead of Subject. In this case you will get the last update even if you subscribe after the broadcast. This is your current situation This code is from RxJS repository in Github

BehaviorSubject gives you only the last value. If you need last 10 or 2 values then use ReplaySubject instead.

    /*
 * BehaviorSubject
 *
 * Subject that remembers the last (or initial) value
 */

var xs = new Rx.BehaviorSubject()
xs.subscribe(logAllObserver('BehaviorSubject'))
//=> BehaviorSubject - Value: undefined

var xs = new Rx.BehaviorSubject('default')
xs.subscribe(logAllObserver('BehaviorSubject'))
//=> BehaviorSubject - Value: default

var xs = new Rx.BehaviorSubject('default')
xs.onNext('new one')
xs.subscribe(logAllObserver('BehaviorSubject'))
//=> BehaviorSubject - Value: new one
Turdaliev Nursultan
  • 2,538
  • 1
  • 22
  • 28
  • can you show me example with it actually getting long error when importing it from rxjs and there is not a good documented page . – Ironsun Apr 04 '16 at 10:59
  • actually i am building the service wrong way , can you atleast give me something how can i use this in my service . i am just all confused because all other examples show use of behvioursubject in a different way which is not making any sense to me , i am still not able to run any example from git – Ironsun Apr 04 '16 at 12:57
  • i dont know how to use plunk but this is what i am trying public space: Subject = new BehaviorSubject(null); – Ironsun Apr 04 '16 at 13:33
  • and in the child console.log('behiob' + shared.space.single()); – Ironsun Apr 04 '16 at 13:33
  • well it says .sinlgle / last etc all are not function error , i dont know how to implement this still strugling done even know what i am doing is right or not :| – Ironsun Apr 04 '16 at 13:34
  • Change your `Subject` into `BehaviorSubject`. – Turdaliev Nursultan Apr 04 '16 at 13:59
  • there is no much information in your answer just edit it http://stackoverflow.com/questions/36404541/behavioursubject-in-angular2-how-it-works-and-how-to-use-it/36404625?noredirect=1#comment60425735_36404625 as per this or add just syntax so i will mark it as answer and will be helpful for others – Ironsun Apr 04 '16 at 14:15
0
import {Injectable,EventEmitter}     from 'angular2/core';
import {Subject} from "rxjs/Subject";
@Injectable()
export class SearchService {

   searchaddressStream$:EventEmitter<Sharedcomponent> = new EventEmitter();

    broadcastaddressChange(address: Sharedcomponent ) {
        this.searchaddressStream$.emit(address);
    }
}

ngOnInit() {
        this.getNewProduct();
        // this.getlocation();
}
ngViewAfterInit()
{
   this.getlocation();
}
micronyks
  • 54,797
  • 15
  • 112
  • 146
  • `EventEmitter` shouldn't be used in services (http://stackoverflow.com/questions/34376854/delegation-eventemitter-or-observable-in-angular2/35568924). `@Output()` in a service is entirely meaningless. – Günter Zöchbauer Apr 04 '16 at 10:47
  • actually i am new to angular2 i never used output and input so do i need to put input in my component if i have an output in service?? – Ironsun Apr 04 '16 at 10:53
  • Gunter thanks for the link.It'd help me to understand Observable better as I'm not too much aware with Observable. So came up with this solution. – micronyks Apr 04 '16 at 10:56
  • @micronyks its not working in ngViewAfterInit rather in ngOnInit but this time i am atleast getting a response undefined undefined undefined so i think the value vanishes – Ironsun Apr 04 '16 at 11:15
  • @micronyks and its not changing values when changed in parent – Ironsun Apr 04 '16 at 11:16