How to view a Search-JSON File (epubjs)

HI,

I want to use the epubjs-search. The search creates a file and I would like to display this report as a search-list. so the User can click (or tap) on a result, and the epub page opens.

How can I create a clickable list?

What kind of file does it create and where? Is this a static file?
Show us an example of what you got or get.

In the book “moby-dick” I search for “Jonah” via url e.g. “http://localhost:5000/search?q=Jonah” and get this example:

{
  "results": [
    {
      "baseCfi": "/6/12[xepigraph_001]!", 
      "cfi": "/6/12[xepigraph_001]!/4/2/14/2", 
      "highlight": "Lord had prepared a great fish to swallow up <b class='match'>Jonah</b>.\u201d ...", 
      "href": "epigraph_001.xhtml", 
      "path": "moby-dick//OPS/epigraph_001.xhtml", 
      "title": "EXTRACTS"
    }, 
    {
      "baseCfi": "/6/30[xchapter_009]!", 
      "cfi": "/6/30[xchapter_009]!/4/2/16", 
      "highlight": "the Scriptures. Yet what depths of the soul does <b class='match'>Jonah</b>\u2019s deep sealine sound! what a pregnant lesson to us ...", 
      "href": "chapter_009.xhtml", 
      "path": "moby-dick//OPS/chapter_009.xhtml", 
      "title": "Chapter 9. The Sermon."
    }, 
    {
      "baseCfi": "/6/30[xchapter_009]!", 
      "cfi": "/6/30[xchapter_009]!/4/2/18", 
      "highlight": "\u201cWith this sin of disobedience in him, <b class='match'>Jonah</b> still further flouts at God, by seeking to flee ...", 
      "href": "chapter_009.xhtml", 
      "path": "moby-dick//OPS/chapter_009.xhtml", 
      "title": "Chapter 9. The Sermon."
    }, 
    {
      "baseCfi": "/6/30[xchapter_009]!", 
      "cfi": "/6/30[xchapter_009]!/4/2/20", 
      "highlight": "the Customs\u2014\u2018Who\u2019s there?\u2019 Oh! how that harmless question mangles <b class='match'>Jonah</b>! For the instant he almost turns to flee again.", 
      "href": "chapter_009.xhtml", 
      "path": "moby-dick//OPS/chapter_009.xhtml", 
      "title": "Chapter 9. The Sermon."
    }
  ]
}

The results array is perfect for looping over. title and highlight can be headline and content of a list item. Tapping on it then would do some kind of navigation based on baseCfi, cfi, href or path.

1 Like

I’ve tried using the following code:

search.ts

import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { NavController, NavParams } from 'ionic-angular';


@Component({
  selector: 'search-book',
  templateUrl: 'search.html'
})
export class SearchPage {

  items:Array<any>;

//http://localhost:5000/search?q=Jonah
//assets/data/search.json

  constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http) {
      //this._http.getRequest().subscribe(res=>this.requests=res);
      this.items = navParams.get('item');
      this.http.get("http://localhost:5000/search?q=Jonah").subscribe (data => {
        this.items = data.json();
        console.log("item log: "+data)
      }, 
      error => { console.log(error);}
    )
  
  }

    ionViewDidLoad() {
    console.log('Hello DetailsBasic Page');
        console.log('Hello DetailsBasic: '+ this.items);

  }
}

search.html

<ion-list>
  <!-- <ion-item>
    <h1>{{items.highlight}}</h1>
    <p>{{items.title}}</p>
    <ion-icon item-right name="arrow-forward"></ion-icon>
  </ion-item> -->

  <ion-list>
    <ion-item-sliding *ngFor="let item of items">
      <ion-item>
    <h1>{{item.highlight}}</h1>
    <p>{{item.title}}</p>
    <ion-icon item-right name="arrow-forward"></ion-icon>
  </ion-item>
    </ion-item-sliding>
  </ion-list>


</ion-list>

And get: Runtime Error

Cannot find a differ supporting object ‘[object Object]’ of type ‘object’. NgFor only supports binding to Iterables such as Arrays.

Consol-Log:

Angular is running in the development mode. Call enableProdMode() to enable the production mode. vendor.js:3405:9
ionViewDidLoad HomePage main.js:99:9
Native: tried calling StatusBar.styleDefault, but Cordova is not available. Make sure to include cordova.js or run in a device/simulator vendor.js:56450:9
Native: tried calling SplashScreen.hide, but Cordova is not available. Make sure to include cordova.js or run in a device/simulator vendor.js:56450:9
show Object { label: “Niro iframe Book 1”, file: “assets/books/epub/iframe_open_java.…” } main.js:102:9
_updateTotalPages main.js:233:9
subscribe to events main.js:183:9
ionViewDidLoad BookPage main.js:177:9
Speicherverbrauch von “will-change” ist zu hoch. Die Budget-Grenze ist die Fläche des Dokuments multipliziert mit 3 (187850 px). Vorkommen von “will-change”, die das Budget überschreiten, werden ignoriert. localhost:8100
updatePageTitle main.js:247:9
updatePageTitle title = [No data] main.js:255:9
UNDEFINED key : value = RESEND_ACTIVATION : undefined language.controller.js:102:17
updateTotalPages totalPages = 10 main.js:239:13
search main.js:280:9
Hello DetailsBasic Page main.js:360:9
Hello DetailsBasic: undefined main.js:361:9
"item log: Response with status: 200 OK for URL: http://localhost:5000/search?q=Jonah" main.js:356:13
ERROR Error: Cannot find a differ supporting object ‘[object Object]’ of type ‘object’. NgFor only supports binding to Iterables such as Arrays.
Stack-Trace:
NgForOf.prototype.ngOnChanges@http://localhost:8100/build/vendor.js:40013:27
checkAndUpdateDirectiveInline@http://localhost:8100/build/vendor.js:11171:9
checkAndUpdateNodeInline@http://localhost:8100/build/vendor.js:12597:17
checkAndUpdateNode@http://localhost:8100/build/vendor.js:12536:16
debugCheckAndUpdateNode@http://localhost:8100/build/vendor.js:13239:38
debugCheckDirectivesFn@http://localhost:8100/build/vendor.js:13180:13
View_SearchPage_0/<@ng:///AppModule/SearchPage.ngfactory.js:162:5
debugUpdateDirectives@http://localhost:8100/build/vendor.js:13165:12
checkAndUpdateView@http://localhost:8100/build/vendor.js:12503:5
callViewAction@http://localhost:8100/build/vendor.js:12866:21
execComponentViewsAction@http://localhost:8100/build/vendor.js:12798:13
checkAndUpdateView@http://localhost:8100/build/vendor.js:12509:5
callViewAction@http://localhost:8100/build/vendor.js:12866:21
execEmbeddedViewsAction@http://localhost:8100/build/vendor.js:12824:17
checkAndUpdateView@http://localhost:8100/build/vendor.js:12504:5
callViewAction@http://localhost:8100/build/vendor.js:12866:21
execComponentViewsAction@http://localhost:8100/build/vendor.js:12798:13
checkAndUpdateView@http://localhost:8100/build/vendor.js:12509:5
callViewAction@http://localhost:8100/build/vendor.js:12866:21
execComponentViewsAction@http://localhost:8100/build/vendor.js:12798:13
checkAndUpdateView@http://localhost:8100/build/vendor.js:12509:5
callViewAction@http://localhost:8100/build/vendor.js:12866:21
execEmbeddedViewsAction@http://localhost:8100/build/vendor.js:12824:17
checkAndUpdateView@http://localhost:8100/build/vendor.js:12504:5
callViewAction@http://localhost:8100/build/vendor.js:12866:21
execComponentViewsAction@http://localhost:8100/build/vendor.js:12798:13
checkAndUpdateView@http://localhost:8100/build/vendor.js:12509:5
callWithDebugContext@http://localhost:8100/build/vendor.js:13565:39
debugCheckAndUpdateView@http://localhost:8100/build/vendor.js:13105:12
ViewRef
.prototype.detectChanges@http://localhost:8100/build/vendor.js:10577:54
ApplicationRef
.prototype.tick/<@http://localhost:8100/build/vendor.js:5434:58
ApplicationRef
.prototype.tick@http://localhost:8100/build/vendor.js:5434:13
next/<@http://localhost:8100/build/vendor.js:5314:100
f</t.prototype.invoke@http://localhost:8100/build/polyfills.js:3:9281
onInvoke@http://localhost:8100/build/vendor.js:4508:28
f</t.prototype.invoke@http://localhost:8100/build/polyfills.js:3:9208
c</r.prototype.run@http://localhost:8100/build/polyfills.js:3:4433
NgZone.prototype.run@http://localhost:8100/build/vendor.js:4376:51
next@http://localhost:8100/build/vendor.js:5314:70
EventEmitter.prototype.subscribe/schedulerFn<@http://localhost:8100/build/vendor.js:4210:36
SafeSubscriber.prototype._tryOrUnsub@http://localhost:8100/build/vendor.js:36130:13
SafeSubscriber.prototype.next@http://localhost:8100/build/vendor.js:36077:17
Subscriber.prototype.next@http://localhost:8100/build/vendor.js:36017:9
Subscriber.prototype.next@http://localhost:8100/build/vendor.js:35981:13
Subject.prototype.next@http://localhost:8100/build/vendor.js:36478:17
EventEmitter.prototype.emit@http://localhost:8100/build/vendor.js:4196:54
NgZone.prototype.checkStable@http://localhost:8100/build/vendor.js:4473:17
NgZone.prototype.onLeave@http://localhost:8100/build/vendor.js:4549:9
onInvokeTask@http://localhost:8100/build/vendor.js:4502:21
f</t.prototype.invokeTask@http://localhost:8100/build/polyfills.js:3:9869
c</r.prototype.runTask@http://localhost:8100/build/polyfills.js:3:5124
t/this.invoke@http://localhost:8100/build/polyfills.js:3:10938
SearchPage.ngfactory.js:145:6
View_SearchPage_0 ng:///AppModule/SearchPage.ngfactory.js:145:6
proxyClass http://localhost:8100/build/vendor.js:91238:20
DebugContext
.prototype.logError http://localhost:8100/build/vendor.js:13505:11
ErrorHandler.prototype.handleError http://localhost:8100/build/vendor.js:1503:9
IonicErrorHandler.prototype.handleError http://localhost:8100/build/vendor.js:112975:9
ApplicationRef
.prototype.tick http://localhost:8100/build/vendor.js:5441:13
next/< http://localhost:8100/build/vendor.js:5314:100
f</t.prototype.invoke http://localhost:8100/build/polyfills.js:3:9281
onInvoke http://localhost:8100/build/vendor.js:4508:28
f</t.prototype.invoke http://localhost:8100/build/polyfills.js:3:9208
c</r.prototype.run http://localhost:8100/build/polyfills.js:3:4433
NgZone.prototype.run http://localhost:8100/build/vendor.js:4376:51
next http://localhost:8100/build/vendor.js:5314:70
EventEmitter.prototype.subscribe/schedulerFn< http://localhost:8100/build/vendor.js:4210:36
SafeSubscriber.prototype.__tryOrUnsub http://localhost:8100/build/vendor.js:36130:13
SafeSubscriber.prototype.next http://localhost:8100/build/vendor.js:36077:17
Subscriber.prototype._next http://localhost:8100/build/vendor.js:36017:9
Subscriber.prototype.next http://localhost:8100/build/vendor.js:35981:13
Subject.prototype.next http://localhost:8100/build/vendor.js:36478:17
EventEmitter.prototype.emit http://localhost:8100/build/vendor.js:4196:54
NgZone.prototype.checkStable http://localhost:8100/build/vendor.js:4473:17
NgZone.prototype.onLeave http://localhost:8100/build/vendor.js:4549:9
onInvokeTask http://localhost:8100/build/vendor.js:4502:21
f</t.prototype.invokeTask http://localhost:8100/build/polyfills.js:3:9869
c</r.prototype.runTask http://localhost:8100/build/polyfills.js:3:5124
t/this.invoke http://localhost:8100/build/polyfills.js:3:10938
ERROR CONTEXT Object { view: Object, nodeIndex: 8, nodeDef: Object, elDef: Object, elView: Object } SearchPage.ngfactory.js:145:6

Do a console.log on the object you have right now and look at it.
Also have a look at the JSON again that you posted.

You change the value of this.items, causing it to do two different jobs. Use different variables for different jobs.

@Sujan12
it’s show me:
consol.log:
Data item: [object Object]
"Data: : Response with status: 200 OK for URL: http://localhost:5000/search?q=Jonah"

@AaronSterling

Error is gone, thanks but now I see only one white page without any msg :confused:

i change this:

into

      this.http.get("http://localhost:5000/search?q=Jonah").subscribe (data => { this.requests = data.json();

You should be able to click that object to see its structure.
Why this.requests?

Look carefully at what you posted here. It is an object. It is not an array. It has a results property which is in fact an array. That is what you should be looping over. You are not. You are trying to loop across the entire object, which makes no sense and makes Angular’s change detector angry with you, hence the error message that tells you that it can’t loop over an object.

1 Like

thx all. it works:

search.ts

import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { NavController, LoadingController } from 'ionic-angular';
import {HttpProvider} from '../../providers/http-provider';

@Component({
  selector: 'search-book',
  templateUrl: 'search.html',
  providers:[HttpProvider]
})
export class SearchPage {

  newsData:any;
  loading:any;

//http://localhost:5000/search?q=Jonah
//assets/data/search.json

  constructor(public navCtrl: NavController, private httpProvider:HttpProvider, public loadingCtrl: LoadingController) {
    
   this.loading = this.loadingCtrl.create({
      content: `
      <ion-spinner ></ion-spinner>` 
    });

    this.getdata();
    
  
  }
  getdata(){
    //this.loading.present();
    //this.http.get('http://localhost:5000/search?q=Jonah').map(res => res.json());
    //this.http.get("http://localhost:5000/search?q=Jonah").subscribe (data => { this.requests = data.json();
    this.httpProvider.getJsonData().subscribe(
      result => {
        //this.newsData=result.data.children;
        this.newsData=result.results;
        console.log("Success : "+this.newsData);
      },
      err =>{
        console.error("Error : "+err);
      } ,
      () => {
        console.log('getData completed');
      }
  );
}


    ionViewDidLoad() {
    console.log('Hello ionic view :)');

  }
}

search.html

<ion-header>
<ion-navbar>
<ion-title>
search results
</ion-title>
</ion-navbar>
</ion-header>

<ion-content padding>
<ion-list >
<ion-item text-wrap *ngFor="let item of newsData" >
<p >{{item.highlight}}</p>
</ion-item>
</ion-list>
</ion-content>

And i create a “provider” page with:
http-provider.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

/*
  Generated class for the HttpProvider provider.

  See https://angular.io/docs/ts/latest/guide/dependency-injection.html
  for more info on providers and Angular DI.
*/

  //http://localhost:5000/search?q=Jonah

@Injectable()
export class HttpProvider {

  constructor(public http: Http) {
    console.log('Hello Provider ');
  }
  getJsonData(){
  return this.http.get('http://localhost:5000/search?q=Jonah').map(res => res.json());
}

}

Output:

1 Like

Don’t do this. Only declare it in the app module. The way you have it creates a new provider for each page using it.

1 Like

Now you only have to make it actually interpret these <b>s as HTML :smiley:

@rapropos Thank you :slight_smile:

@Sujan12 right :wink: I’m already working, do you have an idea?

Next question: