$scope not updating after passing to new view with $location.path - angularjs

I have a simple CRUD I put together with Angularjs. From a product list display I pass the user to a new view template for the "Create New" form.
The form processes fine and updates the database. I then pass the user back to the list display using "$location.path(url)".
For some reason when the list page displays, the changes do not appear in the $scope and you have to refresh the page to see the changes.
Sample code:
$scope.acns = acnFactory.query()
.$promise.then(function (data) {
$scope.acns = data;
});
the above displays the list of items.
$scope.createAcn = function () {
$scope.acn.isActive = true;
acnFactory.create($scope.acn);
$location.path('/acn');
}
The above POSTs the new product then redirects to the list page (/acn)
My assumption is that the list page will reprocess or watch the changes to the $scope but the view does not update.

The problem is most probably here:
$scope.createAcn = function () {
$scope.acn.isActive = true;
acnFactory.create($scope.acn);
$location.path('/acn');
}
creating a product most certainly consists in sending an HTTP request to the server. This is asynchronous. This means that acnFactory.create() returns immediately after the request has been sent. Not after the response has been received.
So, this code sends the request to create the product and immediately goes to the page which lists the products. The GET request sent to get the product list is thus sent almost at the same instant as the one used to create the new product. The two requests are handled concurrently by the server, and the returned list contains the list without the new product, which is being created in a separate transaction.
You need to wait for the response to come back, and make sure it's successful, before going to the product list. Assuming the service returns a promise, as it should do:
$scope.createAcn = function () {
$scope.acn.isActive = true;
acnFactory.create($scope.acn).then(function() {
$location.path('/acn');
});
};

Related

Sencha extjs model.erase removes model even when server error

When calling model.erase({failure..., success...}) the model is removed even when the server responds with a HTTP StatusCode 500. The failure listener is triggered correctly but i would expect that model is not destroyed then. I can see that it is destroyed because it gets removed from the store.
var rec = store.getAt(index);
rec.erase({
success:function(record, operation){
// Do something to notify user knows
}
failure:function(record, operation){
// correctly triggered when HTTP = 40x or 50x
// Would expect that record is still in store. Why not?
// Of course i could add it again to store with store.add(record) but is that the prefered way?
}
});
I am using an AJAX proxy in Extjs 6.0
Yes, the erase method removes the record from the store right away, without waiting for the server's response. The "hacky" way to handles you scenario will be:
set the record's dropped property to true;
save the record using the save method (it will generate a delete request but will keep the record in the store);
remove the record from the store on success, reset the dropped property to false of failure.
var record = store.getAt(index);
record.dropped = true;
record.save({
success: function() {
store.remove(record);
// do something to notify the user
}
failure: function() {
record.dropped = false;
}
});
The erase isn't really relevant here. Calling erase calls the model drop method, which marks it as pending deletion and removes it from any stores. Just because the server failed to delete it from the server doesn't necessarily mean you want it back in the store, it's still just pending deletion.

how to fetch the record from mongodb to part of html page automaticalyy without refreshing/reloading manually. using MEAN stack

Need some help reading Mean stack. I have a requirement like,
When a record is inserted into database, part of html page should get displayed with the new inserted record without reloading/refreshing manually.
Html page should get automatically updated with new record.
observations so far:
I am already using angularjs, nodejs and mongodb.
Using refresh() function, able to update part of hrml page manually.
I am to insert the record from html page to mongodb.
You should use websockets ( socket.io is a good option ).
In the route responsible for document insertion/update on the backend, you should emit a new_document signal with the document's body to all sockets in the site...
Example:
app.post('/api/posts', (req, res) => {
Post.insert(postBody).then(body => {
io.emit('new_document', body); // Broadcast to all websocket clients
res.json(body);
}).catch(err => {
console.error(err);
res.status(500).json({error: err.message});
});
});
Then, in the front-end, you should listen for the new_document event and call the refresh() function as callback or, even better, write a function to add just the new document.
Example:
socket.on('new_document', function (body) {
// ... code to add body to HTML ...
});

My flux store gets re-instantiated on reload

Okay. I'm kinda new to react and I'm having a #1 mayor issue. Can't really find any solution out there.
I've built an app that renders a list of objects. The list comes from my mock API for now. The list of objects is stored inside a store. The store action to fetch the objects is done by the components.
My issue is when showing these objects. When a user clicks show, it renders a page with details on the object. Store-wise this means firing a getSpecific function that retrieves the object, from the store, based on an ID.
This is all fine, the store still has the objects. Until I reload the page. That is when the store gets wiped, a new instance is created (this is my guess). The store is now empty, and getting that specific object is now impossible (in my current implementation).
So, I read somewhere that this is by design. Is the solutions to:
Save the store in local storage, to keep the data?
Make the API call again and get all the objects once again?
And in case 2, when/where is this supposed to happen?
How should a store make sure it always has the expected data?
Any hints?
Some if the implementation:
//List.js
componentDidMount() {
//The fetch offers function will trigger a change event
//which will trigger the listener in componentWillMount
OfferActions.fetchOffers();
}
componentWillMount() {
//Listen for changes in the store
offerStore.addChangeListener(this.retriveOffers);
}
retrieveOffers() {
this.setState({
offers: offerStore.getAll()
});
}
.
//OfferActions.js
fetchOffers(){
let url = 'http://localhost:3001/offers';
axios.get(url).then(function (data) {
dispatch({
actionType: OfferConstants.RECIVE_OFFERS,
payload: data.data
});
});
}
.
//OfferStore.js
var _offers = [];
receiveOffers(payload) {
_offers = payload || [];
this.emitChange();
}
handleActions(action) {
switch (action.actionType) {
case OfferConstants.RECIVE_OFFERS:
{
this.receiveOffers(action.payload);
}
}
}
getAll() {
return _offers;
}
getOffer(requested_id) {
var result = this.getAll().filter(function (offer) {
return offer.id == requested_id;
});
}
.
//Show.js
componentWillMount() {
this.state = {
offer: offerStore.getOffer(this.props.params.id)
};
}
That is correct, redux stores, like any other javascript objects, do not survive a refresh. During a refresh you are resetting the memory of the browser window.
Both of your approaches would work, however I would suggest the following:
Save to local storage only information that is semi persistent such as authentication token, user first name/last name, ui settings, etc.
During app start (or component load), load any auxiliary information such as sales figures, message feeds, and offers. This information generally changes quickly and it makes little sense to cache it in local storage.
For 1. you can utilize the redux-persist middleware. It let's you save to and retrieve from your browser's local storage during app start. (This is just one of many ways to accomplish this).
For 2. your approach makes sense. Load the required data on componentWillMount asynchronously.
Furthermore, regarding being "up-to-date" with data: this entirely depends on your application needs. A few ideas to help you get started exploring your problem domain:
With each request to get offers, also send or save a time stamp. Have the application decide when a time stamp is "too old" and request again.
Implement real time communication, for example socket.io which pushes the data to the client instead of the client requesting it.
Request the data at an interval suitable to your application. You could pass along the last time you requested the information and the server could decide if there is new data available or return an empty response in which case you display the existing data.

NodeJS update user status dynamically with Angular

I have this little issue. I have a service that has a Subscription option. When an item in the DataBase is modified (i.e. customer order), I want the customer to see the change in real-time.
Once the user logs in, he is automatically subscribed to his order's status (or several orders, as the case may be). When the status changes, the service sends a POST to a URL that I designate and when that is done, I want to change the client's order status, however I have no idea how to modify Angular's model in order to change what the user sees.
module.exports = function (app) {
app.route('/api/machine')
.post(function (req, res) {
console.log(JSON.stringify(req.body));
return res.send("post returned " + JSON.stringify(req.body));
})
};
At the moment, I get the updates from the Service and print them out, but how do I update the view as well?
try use $watch() function.. when the value is modified, the view is updated.
$scope.$watch(function(scope) { return scope.data.myVar },
function(newValue, oldValue) {
document.getElementById("").innerHTML =
"" + newValue + "";
}
);
I dont know how you've constructed this project's structure, but if you're using a API, use http post to notify your front when changes are done.
the digest or watch, will make your controller do a function always the value has changed.
Angular Digest,Watch and Apply docs.
i hope this helps.
cya.

Callbacks in views

This may be more of a question around design pattern - I hope it makes sense.
I am using backbone - am developing a relatively simple app where user can add requests (where the request model is simply heading, description and price). The only requirement to add the requests is that a user is 'logged in'.
However I wish that the user 'adds' the request before checking if the user is logged in (remove one barrier). By that I mean that the user fills the form in, if not registered they have to register and then the request is just sent, if they were logged in it would just be sent. So initially the 'add request' view is rendered, when save is triggered this will call the save on the model which calls the ajax request on the server. The response will either return true (the user was logged in and the request added) or false (the user was not logged in).
So assuming that the user was not logged in - then I would wish to render a new view 'register' which has the option for the user to switch to 'login' (another view). So User in theory could go from
Request (save) -> Register -> Login -> Request (save)
So presuming that the user then registered (filled in the form which then called the registers view save method which then called the registers model save and returned ok). I would then wish to once again call the 'request' save method once again (as now the user would be logged in). However I do not want the register/login tied to the Request view - as in theory a new view (lets say I had a sent message view) would want similar functionality e.g. try and make the request, if failed switch view to register - perform save and then call some callback.
So the question is what is the right way to do this?
1) Do I create some closure inside the request view referencing the 'save' function and store it in a global to be called by register/login onsuccess?
2) Create a closure as above and pass that to the register etc (and if so how would I pass this given register/login is a view).
3) Pass a reference to 'this' of the request view?
So far all I have is, so in the else I would render the 'register' view but would love to know best way to do this without it getting very ugly?
save : function(event){
if(this.model.isValid() == true) {
this.$("#general_error").hide();
this.model.set({'formattedPrice' : TB_H.formatPrice(this.model.get('currency'), this.model.get('price'))});
self = this;
this.model.save(this.model.toJSON(), {
success: function(m, y) {
if(y.status == true) {
self.model = new TB_BB.Request();
Backbone.ModelBinding.bind(self);
Backbone.Validation.bind(self);
$('#add-offer-button').show();
} else {
if(y.errors[0] == 'not logged in') {
this.$("#general_error").html('You are not logged in');
this.$("#general_error").show();
} else {
_.each(y.errors, function(key, val) { this.$("#general_error").html(key) });
this.$("#general_error").show();
}
}
}, error : function(m,y) {
this.$("#general_error").show();
this.$("#general_error").html("Something bad happened - please try again")
}
}
);
}
Greatly appreciate any help!
I noticed this after asking a similar question, which I just deleted. I'm thinking this isn't the way most people are doing it in backbone.
what I did instead was pass my different routes to the same method and if the ids were not null, I'd call the route.
So I have a view
base_view = Backbone.Views.extend({
initialize: function(id,a_id,b_id){
this.id = id;
this.a_id = a_id;
this.b_id = b_id;
Myapp.data = new Myapp.Model.Base();
Myapp.data.url = '/data_url/'+id;
Myapp.data.fetch(Myapp.data, {
success: function(response){
// i have some nested collections, and models so i fill those in here
Myapp.mainModel = new First_Child_Collection(response.attributes.first_child_array);
}, error: function(){
alert('oops couldn't get data');
}
});
Myapp.data.bind("fetched",this.render,this);
},
render: function(){
new Main_View();
new Sub_View_1(this.id);
new Sub_View_2(this.a_id);
new Sub_View_3(this.b_id);
}
});
Then in my routes, rather than having a new route for each, I have
routes: {
"app/new": "new",
"app/:id/edit/a/:a_id/b/:b_id": "edit"
}
edit {
new base_view(id,a_id,b_id);
}
I'm not sure if this is perfect, but I think it is DRY'r than the other options. I just check that a_id or b_id are not undefined before passing those views.
Hope it helps.

Resources