Ionic 4 Angular 7 - passing object/data to another page [duplicate] - ionic-framework

This question already has answers here:
Ionic 4. Alternative to NavParams
(8 answers)
Closed 4 years ago.
I would like to pass a JSON object to another page. What I've tried is to pass the JSON string using Angular router ActivatedRoute like this:
this.router.navigate(['details', details]);
and then retrieve it like this:
import { ActivatedRoute } from '#angular/router';
constructor(private activatedRoute: ActivatedRoute) {
}
ngOnInit() {
this.activatedRoute.params.subscribe(extras => {
console.log(extras);
this.JSONObject = extras;
});
}
It is possible to do it this way but what happened was the nested JSON objects becomes inaccessible. It turns into this string:
"[object Object]"
The stringified JSON object is fine and accessible before I pass it. Another problem is that it appends the JSON string to the url so it doesn't look that nice. From what I read as well, it is not a good practice to pass something more than just an id this way.
I am thinking of something like passing objects as intent extras between activities in Android. I've searched the documentations, forums, and previous stackoverflow questions but I didn't found any solution that enables me to achieve this. Is there any other way of passing objects between pages using Angular router in Ionic4?

I solved it using a service with a simple setter and getter just like in this question that I later found:
Ionic 4. Alternative to NavParams
First, I create a service with setter & getter:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class NavExtrasService {
extras: any;
constructor() { }
public setExtras(data){
this.extras = data;
}
public getExtras(){
return this.extras;
}
}
Let's say I'm navigating from page A to page B, in page A:
this.navExtras.setExtras(extras)
this.router.navigateByUrl('page-b');
Then in Page B, I retrieve the extras this way:
this.location = navExtras.getExtras();
It works so far although I'm still not sure if there are better ways to do it..

Related

"TypeError: this.types is not a function" when using "vuex-orm-decorators"

I'm trying to use the npm package 'vuex-orm-decorators' from https://github.com/scotley/vuex-orm-decorators#readme
When I try to insert into the DB, I get the error TypeError: this.types is not a function
Entity looks like this
import { Model } from "#vuex-orm/core";
import { NumberField, OrmModel, StringField } from "vuex-orm-decorators";
#OrmModel("races")
export default class Race extends Model {
#NumberField()
public ID!: number;
#StringField()
public Name!: string;
}
store looks like this:
import Vue from "vue";
import Vuex from "vuex";
import { ORMDatabase } from "vuex-orm-decorators";
Vue.use(Vuex);
export default new Vuex.Store({
.
.
.
plugins: [ORMDatabase.install()]
});
Also, maybe this is a clue.... in Vuex-Orm, this.setters is returning a value, but this.setters('all') is returning undefined.
/**
* Get all records.
*/
Model.all = function () {
return this.getters('all')();
};
From seeing the undefined basic fields and functions, it seems like the vuex-orm database isn't getting set up correctly. Any ideas?
I tried to create a stackoverflow tag for vuex-orm-decorators, but I'm not quite at 1500 rep yet, so I just tagged it as vuex-orm.
There is a small bug in vuex-orm-decorators package in the implementation of the types function defined in Vuex-ORM Single Table Inheritance docs.
I've created a fork in which I fixed this simple problem and created a pull request to update the original package.
Lastly, I've to point that from my tiny dive into this package that it isn't fully ready yet for table inheritance features built in Vuex-ORM but still is great for simple use cases.

Paths/links with unique ID's angular2

I'm creating a quiz making/sharing website using angular2 but am not sure how to share the quizzes. i was thinking of using each of my quizzes identifiers as URLs. The quizzes are made using forms and are saved on a docmentdb as JSON. they have unique ID's to identify them. Any ideas as to how i could do this?
Those URLs must be dynamically created, as new quizzes can be submitted and thereafter accessed.
You can use the same base url for your page with quiz, but differentiate quizzes by path parameter like:
quizsite.com/#/quiz/12 (12 being quiz id)
Inside your component you can read what path parameters are located in your url and their values by accessing ActivateRoute object:
Component
import { Component } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
#Component({
templateUrl: 'quizComponent.html',
})
export class QuizComponent {
constructor(private activatedRoute: ActivatedRoute){}
ngOnInit() {
// Reason for this being a observable is that you can watch
parameter changing (manually in url, or programmatically)
and without any page refresh, read new parameter and change you quiz
this.activatedRoute.params.subscribe(params => {
console.log(params.quizId);
// With this parameter you can make call to your REST API and return
data for that quiz
});
}
}

Creating a SOAP client with angular 2 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm looking for a way to send SOAP request to a web service, with a WSDL. Is it possible to do that with Typescript 2 and Angular 2 ?
I've seen tutorials for Angular 1 but they used old angular methodes, like factory or controller.
I would like if it's possible, a new way to do that with TypeScript.
Any ideas ?
What you need is a service that wraps around Http and provides deserialization:
#Injectable()
export class SOAPService{
constructor(private http:Http){}
public get(url:string, options?:RequestOptionsArgs):Observable<any>{
return this.http.get(url, options).map(res => {
let xmlresult = res.text();
let result = //Here you deserialize your xml object
return result;
}
}
}
Then you can use it this way:
#Component({...})
export class ExampleComponent{
constructor(private soap:SOAPService){}
foo():{
this.soap.get('foo/bar').subscribe(...);
}
}
Since I'm not an xml parsing expert, I can't tell you how to deserialize your XML, but you can check MDN for that, you simply have to wrap the serialization/deserialization process in another service and inject it in your SOAPService.
You could use a regular http-request with Angular2's [Http class] (https://angular.io/docs/ts/latest/api/http/index/Http-class.html)
This is an example from their page:
import {Http, HTTP_PROVIDERS} from '#angular/http';
import 'rxjs/add/operator/map'
#Component({
selector: 'http-app',
viewProviders: [HTTP_PROVIDERS],
templateUrl: 'people.html'
})
class PeopleComponent {
constructor(http: Http) {
http.get('people.json')
// Call map on the response observable to get the parsed people object
.map(res => res.json())
// Subscribe to the observable to get the parsed people object and attach it to the
// component
.subscribe(people => this.people = people);
}
}
instead of asking for a json file, you could use a URL instead.

Angular2 multiple components using one REST call

I am part of a Angular2 application (we use beta3) and the issue is the following:
Usually we have a component that uses some service that uses some rest call and the component displays the data. Great.
However we do have a page with more then 6 components all of them using the same REST call...(the backend returns data for ALL of them) and it doesn't make sense to call 6 times the REST for each component, also it will be weird if we do some client side caching.
Is there something available out of the box ? Or a Pattern to handle such case?
Thanks.
Just do it in a shared service. If you add it only in bootstrap(..., [OtherProviders, HTTP_PROVIDERS, MyService]) each component will get injected the same instance. Store the data in the service and every component can access it
export class MyComponent {
constructor(private dataService:MyService) {
dataService.getData().subscribe(data => { this.data = data; });
}
}
export class MyService {
getData() {
if(!this.data) {
return http.get(...).map(...).subscribe(data => { this.data = data;});
}
return this.data;
}
}
The #Günter's answer really makes sense!
I don't know your code is organized but observable can also be subscribed several times. To do that you need to make them "hot" using the share operator:
export class MyService {
dataObservable:Observable;
initDataObservable() {
this.dataObservable = http.get(...).map(...).share();
}
}
Without using the share operator, corresponding request will executed several times (one per subscribe).
You can notice that the request will be executed once one subscribe method is called on the observable.

How to create a custom 404 page handler with Play 2.0?

What’s the preferred way to handle 404 errors with Play 2.0 and show a nice templated view?
You can override the onHandlerNotFound method on your Global object, e.g.:
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(views.html.notFound(request))
}
}
Please note that there are really two different problems to solve:
Showing a custom 404 page when there is "no handler found", e.g. when the user goes to an invalid URL, and
Showing a custom 404 (NotFound) page as a valid outcome of an existing handler.
I think the OP was referring to #2 but answers referred to #1.
"No Handler Found" Scenario
In the first scenario, for "no handler found" (i.e. invalid URL), the other answers have it right but to be more detailed, per the Play 2.1 documentation as:
Step 1: add a custom Global object:
import play.api._
import play.api.mvc._
import play.api.mvc.Results._
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(
views.html.notFoundPage(request.path)
)
}
}
Step 2: add the template. Here's mine:
#(path: String)
<html>
<body>
<h1>Uh-oh. That wasn't found.</h1>
<p>#path</p>
</body>
</html>
Step 3: tweak your conf/application.conf to refer to your new "Global". I put it in the controllers package but it doesn't have to be:
...
application.global=controllers.Global
Step 4: restart and go to an invalid URL.
"Real Handler can't find object" Scenario
In the second scenario an existing handler wants to show a custom 404. For example, the user asked for object "1234" but no such object exists. The good news is that doing this is deceptively easy:
Instead of Ok(), surround your response with NotFound()
For example:
object FruitController extends Controller {
def showFruit(uuidString: String) = Action {
Fruits.find(uuidString) match {
case Some(fruit) => Ok(views.html.showFruit(fruit))
// NOTE THE USE OF "NotFound" BELOW!
case None => NotFound(views.html.noSuchFruit(s"No such fruit: $uuidString"))
}
}
}
What I like about this is the clean separation of the status code (200 vs 404) from the HTML returned (showFruit vs noSuchFruit).
HTH
Andrew
If you want to do the same using Java instead of Scala you can do it in this way (this works for play framework 2.0.3):
Global.java:
import play.GlobalSettings;
import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Http.RequestHeader;
public class Global extends GlobalSettings {
#Override
public Result onHandlerNotFound(RequestHeader request) {
return Results.notFound(views.html.error404.render());
}
}
Asumming that your 404 error template is views.html.error404 (i.e. views/error404.scala.html).
Please note that Play development team are making lots of efforts to move away from global state in Play, and hence GlobalSettings and the application Global object have been deprecated since version 2.4.
HttpErrorHandler.onClientError should be used instead of
GlobalSettings.onHandlerNotFound. Basically create a class that inherits from HttpErrorHandler, and provide an implementation for onClientError method.
In order to find out type of error (404 in your case) you need to read status code, which is passed as a one of the method arguments e.g.
if(statusCode == play.mvc.Http.Status.NOT_FOUND) {
// your code to handle 'page not found' situation
// e.g. return custom implementation of 404 page
}
In order to let Play know what handler to use, you can place your error handler in the root package or configure it in application.conf using play.http.errorHandler configuration key e.g.
play.http.errorHandler = "my.library.MyErrorHandler"
You can find more details on handling errors here: for Scala or Java.
This works in 2.2.1. In Global.java:
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise.<SimpleResult>pure(notFound(
views.html.throw404.render()
));
}
Ensure that you have a view called /views/throw404.scala.html
This works in 2.2.3 Play - Java
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise<SimpleResult>pure(Results.notFound(views.html.notFound404.render()));
}
html should be within /views/notFound404.scala.html
Dont forget to add Results.notFounf() and import play.mvc.Results;
For Java, if you want to just redirect to main page, I solved it by this.
#Override
public Promise<Result> onHandlerNotFound(RequestHeader request) {
return Promise.pure(redirect("/"));
}