For certain reasons I'd like to build an in-app like REST endpoint in my ionic 3 app. Then frontend components should be able to call data from the in-app backend by simple http.request. I.E. like so:
this.http.request("/#/api/local/getUsers", requestOptions).subscribe(
(rc) => { console.log(rc.text()); },
(err) => { console.log(err) }
);
The result of this request should be a json list of valid users (whatever, determined by the registered controller and request parameters).
I have succeeded to register the path for a component like so:
#IonicPage({
name: 'api',
segment: 'local/:method',
})
#Component({
selector: 'page-fgttm',
templateUrl: 'fgttm.html',
})
export class FgttmPage ...
And when I navigate to /#/api/local/getUsers I can see the (unfortunately HTML) output like written in fgttm.html.
But the this.http.request("/#/api/local/getUsers" just recieves the plain index.html template (far away from json but at least a 200).
What am I missing here? Is there a way to bind an ionic-provider to a path (like a controller in angular or drupal)?
EDIT: I have also tried to use ionic-native/deeplinks. Doesn't work. My deeplink routes get called when I click on a link in the device browser like expected. But the routes do not get called when I try to access them via the http.request(myscheme://myurl.com/api etc. from inside the app.
EDIT2: Using an in-app light-httpd server (ionic-native/httpd) is also not an option because testing in Chrome wouldn't be possible.
Related
We're using Next.Js in next export mode (static HTML export), and we need advanced dynamic routing.
Our routes will look like /[config1]/[config2]/[optionalConfig?]/page, where one segment is optional and the page names are fixed. For example a/b/c/page1 or a1/b1/page2. The pages need the configuration segment data to render.
I haven't found any way to do this with the built-in routing. I can do /pages/[config1]/[config2]/page1.tsx, but that optional segment seems to be an issue. Note that a custom server does not appear to be an option, as we have to use next export mode due to other constraints.
NOTE: We don't know the paths at build time; they represent part of our runtime configuration. This has to use client-side routing. (We do know the finite set of pages - say page1 ... page10 - but the routes to those pages will vary.)
I've tried switching to React Router, setting useFileSystemPublicRoutes: false and adding routes to pages/_app.tsx (Custom App). That almost works, but I see many 404s for on-demand-entries-utils.js in the console as well as some "Possible EventEmitter memory leak detected" warnings (in development mode).
Valid solutions (must work 100% client-side):
Way to do this with built-in routing
Example of integrating React Router with Next.Js
Alternative library (I've looked at next-routes but that hasn't been updated in 3 years)
UPDATE
We may be able to eliminate the requirement of an optional segment. However, it appears that we have to implement getStaticPaths and specify all of the routes. For example:
pages/[config]/foo.tsx
export async function getStaticPaths() {
// Runs at build time
return {
paths: [{ params: { config: 'xyz' } }],
fallback: false,
};
}
export async function getStaticProps(context) {
return {
props: {},
};
}
export default function FooPage(): JSX.Element {
return <div>FOO</div>;
}
This will generate
┌ ○ /
├ /_app
├ ● /[config]/foo
├ └ /xyz/foo
The issue is that we do not know the config at build time.
We need dynamic client-side routing. We'd like to stay with Next.js, as eventually we may be able to use SSR, but that's not an option at the moment.
You can create a catch-all route to grab the parameters, including the optional one, and then you'll need to render the right component based on that. So if you created:
pages/[...config].tsx
This is the same as:
pages/[...config]/index.tsx
Then in index.tsx, you can get the config as an array of strings in getStaticProps based on the url. So /config1/config2/optional is [config1, config2, optional] and /config1/config2 is [config1, config2].
So you can use this as a directory path of sorts if you need to add additional subpages under the known and optional paths.
i learn ReactJS, And i have homework task. I need create chat. And i need use mockApi server. I chose Mockoon. Server works fine and i can see my data at React app. But how can i save my data to Api?
this is my axios request:
axios.post(`http://localhost:9000/user/`, { user })
.then(res => {
console.log(res);
})
as i understand {user} should send to api my data.
But if i see at console i can see this:
here what i see at console
my data at config: and not at data: and this only at browser. If i reload page al reseted.
So here question, can i save my data from input to mockapi serve?
This is possible with mockswitch - it supports various connectors example local drive (saves to file system ), github (user defined github account - great if you are doing, mongo etc.
Their docs is available here https://mockswitch.com/docs/#storage
I have a react app using the walmart electrode framework with uses react router. My question is
a) how can push a route during an action trigger? I tried importing push from react-router but I got a method not found error. I tried instead to use browserHistory.push and that sets the url but for some reason login renders only at /#/login?_k=jazzx rather than at /login.
b) how can I get it to do the /resoure urls rather than the hash #/resource urls. It's a single page app. I realize that it's doing that because its a single page app, but Is there a setting for that? Whats the best practice?
c) what is the querystring that electrode is attaching to things - is that for dev only?
export const tryLogin = (returnUrl = '/') => {
return (dispatch) => {
browserHistory.push('/login'); //this doesn't seem to render the route /#/login_k=somestring does work
return dispatch(createLoginAction({ returnUrl }));
};
}
;
The URL /#/login?_k=jazzx implies that you are using a hash history, but you are attempting to change the URL using browserHistory. You should be passing the browserHistory to your <Router> if you want to use the browser history API (aka have clean URLs).
If you use the browserHistory, you will need to have some sort of code on your server to handle routing set up.
I've been wasting all my journey trying to find out a simple tutorial explaining how to make a simple app using ember cli for treating a basic json file...I've read www.ember-cli.com of course, they explain a lot things but..I don't know how to proceed.
Is there a basic example explaining (dummies level) how you make a simple app that parses a json response?
I've used the RESTAdapter, I have build muy model but I don't really know how to make in order to send a kind of response to my template..
this is my persons.js file under app/adapters folder
import DS from 'ember-data';
var ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:8000/persons',
namespace: 'person'
});
export default ApplicationAdapter;
this is my persons.js model file under app/model
import DS from 'ember-data';
export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
occupation: DS.attr('string')
});
This is my handlebars template persons-tmp.hbs file under app/templates/components
<ul>
{{#each model as |item|}}
<li>{{item.firstName}}</li>
{{/each}}
</ul>
My persons.js file undert the folder app/routes
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.findAll('persons');
}
})
and finally the json response of the call to http://localhost:8000/persons:
"person": {
"firstName": "Barack",
"lastName": "Obama",
"occupation": "President"
}
I don't know why but I don't get any data on my template result--..
I also have tried the twilio tutorial (wich is one the best that I've found) ...but even this doesn't work
Sorry for the simplicity!
Your template will not know about the model unless it is defined in your route. Each page of your application should have a corresponding route (if you are using default structure, look in app/routes/yourRoute.js; if you are using pod structure app/your-route/route.js). This is the file where you would hit your model.
If your model is called accounts:
export default Route.extend({
model() {
return this.store.findAll('accounts'),
}
});
Now your template for that route will have access to the model, which comes from your store. Your store uses your adapter to hit the API. If results aren't being returned correctly, make sure the RESTAdapter is serializing the data correctly.
Your model
When you generate your model in ember-cli, you should have entered ember generate model accounts into your terminal/command line. This would create: app/model/accounts.js or (if using pod stucture) app/accounts/model.js.
This model will automatically look to app/adapters/accounts.js if it is there, otherwise it will default to app/adapters/application.js. However, you list a main.js file--which means you are most likely writing this all manually and not using the command line.
If you are using Ember-CLI, you should really try generating everything through the command line/terminal rather than manually adding it yourself. The resolver may give you some unexpected behavior if you are within in an Ember-CLI application.
For the adapter, if your model is called names, it will automatically append it to the namespace/host defined in your application adapter. If you need to get info from superapi.com/names/accounts for instance:
export default RESTAdapter.extend({
host: 'http://superapi.com',
namespace: 'names'
});
If you look in your console, it should tell you the domain you are trying to hit. If you are running on localhost and trying to hit an outside source, your browser may be stopping you for security reasons.
Serving your API locally
If your API is hosted locally on a different port (i.e. in localhost:8000) you can run your ember server through a proxy. When you run your server through the command line you can enter ember server --proxy http://localhost:8000. The benefit of doing this is that you can now update the host of your adapter to api/v1 if your api is normally localhost:8000/api/v1.
Async Data & Promise Chaining
If you aren't getting any errors, Ember is most likely not serving the data fast enough--i.e. it is loading the template before the data is returned from your API. This is when you want to do an RSVP on your model (http://guides.emberjs.com/v1.10.0/routing/asynchronous-routing/)
export default Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
this.store.findAll('persons')
})
},
setupController: function(controller, hash) {
Ember.setProperties(controller, hash);
}
});
Essentially, it will tell your app not to load certain things until the data has been returned from your API--i.e. it promises to do something upon fetching the data and not before.
I am developing a mobile application using Ionic framework. I get a JSON file containing the template and it's controller. The server will push data once there's data in JSON format. The problem is adding the states dynamically, and I have read that it's only possible at the config time.
Please tell me if there's a way to do this through a controller which will only be responsible of receiving and setting the new state and that will also receive the JSON and from it create the new state.
The help is highly appreciated!
Edit
I have found ui-router-extras (http://christopherthielen.github.io/ui-router-extras/#/future), but I don't know how to make it work for my application.
Suppose a controller gets the JSON using $http where the JSON looks like:
{
'name':'preview',
'template':'<h1>Hello</h2>'
}
How to add this state in this controller?
There are some simliar Q & A:
AngularJS - UI-router - How to configure dynamic views - this answer
Start Angular.js route-segment or ui-router after all translations are loaded
Angular - Dynamically Choose Starting State
Which shows, that UI-Router is shipped with a great feature:
$urlRouterProvider.deferIntercept(defer)
Disables (or enables) deferring location change interception.
If you wish to customize the behavior of syncing the URL (for example, if you wish to defer a transition but maintain the current URL), call this method at configuration time. Then, at run time, call $urlRouter.listen() after you have configured your own $locationChangeSuccess event handler.
There are some working plunkers here or here,
showing that in .config() phase we will stop url router:
.config(['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
// States, which we know about from beginning
// could be declared "statically"
$stateProvider
...
// here we say STOP
$urlRouterProvider.deferIntercept();
}
])
Later, in .run() phase, we will 1) configure states via $http 2) enable url routing
.run(['$urlRouter', '$timeout', '$state',
function($urlRouter, $timeout, $state) {
$http
.get("modules.json")
.success(function(data) {
// here we can use some JSON to configure $stateProvider
// in example we can use $timeout to simulate that
$timeout(function(){
// here we turn all on again...
$urlRouter.sync();
$urlRouter.listen();
// there could be some decision, driven by $http load
// we just use some state as default target
$state.go("parent.child");
}, 1000)
...
Check it in action here or there