I'm calling a function to get a response from Http.get() request.
My data retrieve function is this one:
getCharacterDetail(characterId: number) {
return this.http.get(this.characterDetailApiUrl + characterId)
.subscribe(res =>
console.log(res.json())
);
}
Now I have to show this data into a modal window. No idea of what to do.
ng-bootrstrap would be a good option because modal component is available where you could pass the necessary data as an input to the component.
example
Using the code you've provided, here's a rough estimate of what you might be looking for.
app.controller('characterController', function ($scope, $http) {
$scope.getCharacterDetail = function (number) {
return $http.get(this.characterDetailApiUrl + characterId)
.subscribe(res =>
console.log(res.json())
);
}
});
Related
The two of the following result in different things although they look like the same thing.
1
const addBlogPost = dispatch => {
return () => {
dispatch({type: 'add_blogpost'});
}
};
2
const addBlogPost = dispatch => dispatch({type: 'add_blogpost'});
Could anyone point out how are they different?
You can use this site to compile es6 arrow functions to vanilla JS to easily see the difference.
The first one compiles to this
var addBlogPost = function addBlogPost(dispatch) {
return function () {
dispatch({
type: 'add_blogpost'
});
};
};
While the second compiles to this
var addBlogPost = function addBlogPost(dispatch) {
return dispatch({
type: 'add_blogpost'
});
};
The first returns a function that has a dispatch while the second one returns a dispatch directly.
The result will always be the same as both functions are retuning the same thing.
The only difference is:
In the first function, you're returning a function which returns an object that returns dispatch function.
In the second function, you're returning your dispatch function directly.
I have a simple question.
I want to run the function I created in App.js in a different screen.
Each screen is connected to an AppContainer in context.
I'm going to use state on another screen, but I do not know how to do it.
Can you give me a simple example?
_setDefaultLocation = locationKey => {
console.log("call _setDefaultLocation function");
this.setState({ defaultLocation: locationKey });
console.log(this.state.defaultLocation);
this._getCurrent(locationKey);
};
The above function is called this.props._setDefaultLocation (); I tried to do this and it did not work.
import React from "react";
const WeatherContext = React.createContext();
function withWeather(WrappedComponent) {
return function withContext(props) {
return (
<WeatherContext.Consumer>
{value => <WrappedComponent value={value} {...props} />}
</WeatherContext.Consumer>
);
};
}
export { WeatherContext, withWeather };
Context is used to make it like that.
You can use global keyword to make your function global. Then you can use it in any screen.
For example, assume that you have a function is called 'myFunction'. You can implement your function in App.js as following.
global.myFunction = () => {
console.warn('I am a global function...')
// your function body
};
Then you can call this function in any screen just like other function calling..
In your case your function can implement in this format.
global._myFunction = locationKey => {
console.warn('I am a global function...')
// your function body
};
And when you are calling the function call it as _myFunction(locationKey).
NOTE: 'locationKey' is the parameter that you should pass for your function.
Think this solution will help you.
When using a generic modal or toast with a confirm button, it becomes useful to be able to pass an action into this component so it can be dispatched when you click confirm.
The action may look something like this:
export function showConfirm({modalConfirm}) {
return {
type: 'MODALS/SHOW_MODAL',
payload: {
modalId: getUuid(),
modalType: 'CONFIRM',
modalConfirm : modalConfirm,
},
};
}
Where modalConfirm is another action object such as:
const modalConfirm = {
type: 'MAKE_SOME_CHANGES_AFTER_CONFIRM',
payload: {}
}
The modalConfirm action is dispatched inside the modal component using dispatch(modalConfirm) or even dispatch(Object.assign({}, modalConfirm, someResultFromTheModal)
Unfortunatley this solution only works if modalConfirm is a simple redux action object. This system is clearly very limited. Is there anyway you can pass a function (such as a thunk) in instead of a simple object?
Ideally, something full featured likes this:
const modalConfirm = (someResultFromTheModal) => {
return (dispatch, getState){
dispatch({
type: 'MAKE_SOME_UPDATES',
payload: someResultFromTheModal
})
dispatch({
type: 'SAVE_SOME_STUFF',
payload: http({
method: 'POST',
url: 'api/v1/save',
data: getState().stuffToSave
})
})
}
}
Funny, putting an action object in the store and passing it as a prop to a generic dialog is exactly the approach I came up with myself. I've actually got a blog post waiting to be published describing that idea.
The answer to your question is "Yes, but....". Per the Redux FAQ at http://redux.js.org/docs/FAQ.html#organizing-state-non-serializable , it's entirely possible to put non-serializable values such as functions into your actions and the store. However, that generally causes time-travel debugging to not work as expected. If that's not a concern for you, then go right ahead.
Another option would be to break your modal confirmation into two parts. Have the initial modal confirmation still be a plain action object, but use a middleware to watch for that being dispatched, and do the additional work from there. This is a good use case for Redux-Saga.
I ended up using string aliases to an actions library that centrally registers the actions.
Modal emmiter action contains an object with functionAlias and functionInputs
export function confirmDeleteProject({projectId}) {
return ModalActions.showConfirm({
message: 'Deleting a project it permanent. You will not be able to undo this.',
modalConfirm: {
functionAlias: 'ProjectActions.deleteProject',
functionInputs: { projectId }
}
})
}
Where 'ProjectActions.deleteProject' is the alias for any type of complicated action such as:
export function deleteProject({projectId}) {
return (dispatch)=>{
dispatch({
type: 'PROJECTS/DELETE_PROJECT',
payload: http({
method: 'DELETE',
url: `http://localhost:3000/api/v1/projects/${projectId}`,
}).then((response)=>{
dispatch(push(`/`))
}),
meta: {
projectId
}
});
}
}
The functions are registered in a library module as follows:
import * as ProjectActions from '../../actions/projects.js';
const library = {
ProjectActions: ProjectActions,
}
export const addModule = (moduleName, functions) => {
library[moduleName] = functions
}
export const getFunction = (path) => {
const [moduleName, functionName] = path.split('.');
// We are getting the module only
if(!functionName){
if(library[moduleName]){
return library[moduleName]
}
else{
console.error(`Module: ${moduleName} could not be found.`);
}
}
// We are getting a function
else{
if(library[moduleName] && library[moduleName][functionName]){
return library[moduleName][functionName]
}
else{
console.error(`Function: ${moduleName}.${functionName} could not be found.`);
}
}
}
The modalConfirm object is passed in to the modal by props. The modal component requires the getFunction function in the module above. The modalConfirm object is transformed into a function as follows:
const modalConfirmFunction = (extendObject, modalConfirm) => {
const functionFromAlias = getFunction(modalConfirm.functionAlias);
if(functionFromAlias){
dispatch(functionFromAlias(Object.assign({}, modalConfirm.functionInputs, extendObject)));
}
}
As you can see, this function can take in inputs from the modal. It can execute any type of complicated action or thunk. This system does not break time-travel but the centralized library is a bit of a drawback.
I am trying to learn ReactJS with ES6 along with setting up an instance of Fixed-Data-Table. I'm using the ObjectDataExample example from the github repo, but instead of the faker() values fed to the DataListStore, I want to use a DataListStore that gets its cache from a remote JSON resource. This is how I have defined my DataListStore:
class MyDataListStore {
constructor(/* url string */ url) {
this.url = url || 'http://localhost:8080/default-json';
this._cache = [];
this.pageSize = 1;
this.size = 0;
this.getRemoteData(url);
}
getRemoteData() {
/**
* Fetch remote JSON to be used in the store.
*/
var that = this;
fetch(this.url).then(function(response) {
return response.json();
}).then(function(j) {
console.log(j);
//this.pageSize = j["pages"];
that.size = j["total"];
that._cache = j["table"];
if (that._cache) {
// do something here?
}
});
}
getObjectAt(/*number*/ index) /*?object*/ {
if (index < 0 || index > this.size){
return undefined;
}
if (this._cache[index] === undefined) {
//this._cache[index] = this.createFakeRowObjectData(index);
}
return this._cache[index];
}
getSize() {
return this.size;
}
}
module.exports = MyDataListStore;
As you can see I'm following the FakeObjectDataListStore provided with the example from fixed-data-table more or less. The JSON is fetched properly, the _cache is populated with an array of objects, and when you output getSize once getRemoteData has executed, you do get the size of the _cache. However, I haven't figured out how my fixed-data-table Table component should be updated once the data has been fetched. Currently the Table is rendered but is simple blank with no rows.
class ObjectDataExample extends React.Component {
constructor(props) {
super(props);
this.state = {
dataList: new MyDataListStore()
};
}
render() {
var {dataList} = this.state;
return <Table
rowHeight={70} rowsCount={dataList.getSize()} width={1170} height={500} headerHeight={30}>
<Column
header={<Cell>ID</Cell>}
cell={<TextCell data={dataList} col="id" />}
width={50}
fixed={true}
/>
<Column
header={<Cell>Email</Cell>}
cell={<TextCell data={dataList} col="email" />}
width={300}
fixed={true}
/>
</Table>
}
}
module.exports = ObjectDataExample;
I think the main issue is that I don't have any code meant to populate the table once MyDataListStore is populated with the data from the async call. However, I can't find any help from the examples given in the Fixed-Data-Table github repo or the docs. Any idea how to get this done? I assume I need to set up some sort of event listener, but I'm not sure where/how to do this, as I'm still new to both ReactJS and Fixed-Data-Table.
Edit: I should also add that when the page loads, I get the following error:
Uncaught TypeError: Cannot read property 'id' of undefined
once I set the initial this.size to more than 0. So of course the table doesn't have the available data when it's first loading.
Edit 2: After looking into this further, it looks like if I run the fetch in componentDidMount of my ObjectDataExample and use this.setState(); to reset the dataList object, then I get the table updated. However, this looks a little messy and I'd assume there's a better way to do this directly from my MyDataListStore object.
Thanks,
One design issue with the current implementation of MyDataListStore is that it does not provide a way to notify the caller when the data has been loaded.
One possible way you might do this is to implement some sort of factory function (in the example below, I'm pretending that one exists called MyDataListStore.of) that returns a Promise that eventually resolves the MyDataListStore instance once the data loads:
// In the ObjectData component constructor, we call the MyDataListStore
// factory function and once it resolves, we assign it to our
// state. This will cause our component to re-render.
constructor() {
MyDataListStore.of(myDataListStoreUrl).then(store => {
this.setState({ dataList: store });
});
}
Now, once the data in the data list store resolves, our template (specified in your render function) will render correctly.
The DataListStore.of function we used earlier might look something like this:
class MyDataListStore {
static of(url) {
const dataListStore = new MyDataListStore(url);
return dataListStore.getRemoteData().then(() => return dataListStore);
}
/* ... other MyDataListStore properties/methods ... */
}
And finally we need to update the getRemoteData to return a promise. This is what will allow any clients of our MyDataListStore class to be notified that the data has loaded:
getRemoteData() {
/**
* Fetch remote JSON to be used in the store.
*/
var that = this;
// Return the chained promise! This promise will resolve
// after our last callback is called.
return fetch(this.url).then(function(response) {
return response.json();
}).then(function(j) {
console.log(j);
//this.pageSize = j["pages"];
that.size = j["total"];
that._cache = j["table"];
if (that._cache) {
// do something here?
}
});
}
I know this has something to do with using $q and promises, but I've been at it for hours and still can't quite figure out how it's supposed to work with my example.
I have a .json file with the data I want. I have a list of people with id's. I want to have a service or factory I can query with a parameter that'll http.get a json file I have, filter it based on the param, then send it back to my controller.
angular
.module("mainApp")
.controller('personInfoCtrl',['$scope', '$stateParams', 'GetPersonData', function($scope, $stateParams, GetPersonData) {
$scope.personId = $stateParams.id; //this part work great
$scope.fullObject = GetPersonData($stateParams.id);
//I'm having trouble getting ^^^ to work.
//I'm able to do
//GetPersonData($stateParams.id).success(function(data)
// { $scope.fullObject = data; });
//and I can filter it inside of that object, but I want to filter it in the factory/service
}]);
Inside my main.js I have
//angular.module(...
//..a bunch of urlrouterprovider and stateprovider stuff that works
//
}]).service('GetPersonData', ['$http', function($http)
{
return function(id) {
return $http.get('./data/people.json').then(function(res) {
//I know the problem lies in it not 'waiting' for the data to get back
//before it returns an empty json (or empty something or other)
return res.data.filter(function(el) { return el.id == id)
});
}
}]);
The syntax of the filtering and everything works great when it's all in the controller, but I want to use the same code in several controls, so I'm trying to break it out to a service (or factory, I just want the controllers to be 'clean' looking).
I'm really wanting to be able to inject "GetPersonData" to a controller, then call GetPersonData(personId) to get back the json
You seems to be syntax issue in your filter function in the service.
.service('GetPersonData', ['$http', function($http){
return function(id) {
return $http.get('./data/people.json').then( function (res) {
return res.data.filter(function(el) { return el.id == id });
});
}}]);
But regarding the original issue you cannot really access the success property of the $q promise that you are returning from your function because there is no such property exist, It exists only on the promise directly returned by the http function. So you just need to use the then to chain it through in your controller.
GetPersonData($stateParams.id).then(function(data){ $scope.fullObject = data; });
If you were to return return $http.get('./data/people.json') from your service then you will see the http's custom promise methods success and error.