New Object not triggering createRecord in DataSource - sproutcore

In my responder I have:
Spanish.ADDWORD = SC.Responder.create({
didBecomeFirstResponder: function(responder) {
var store = this._store = Spanish.store.chain(); //buffer changes
var word = store.createRecord(Spanish.Word, {word: "", english: ""});
Spanish.addWordController.set("content",word);
//show the dialog
var pane = Spanish.getPath('addWordPage.mainPane');
pane.append();
pane.makeFirstResponder();
},
submit: function(){
this._store.commitChanges().destroy();
Spanish.makeFirstResponder(Spanish.READY);
}
}
Before I had the DataSource hooked-up, and I was using local, everything worked. When I click submit now no new object is created and createRecord is not being called.

A possible problem is that you are calling .destroy() immediately. This shouldn't be an issue, but as you said it was working while using fixtures (which are synchronous). Now that you are using a dataSource (which is usually asynchronous), it may be getting interrupted. Try removing the .destory(), and see if that resolves your issue.
Another option to try, is that there may be a bug in the nested store, in that if you create a new record (rather than edit an existing one), the 'did it change' test may fail (as there is nothing to compair it too), so calling commitChanges(YES) will force a commit, without the check.

Related

How to refresh previously bound entity every time user visits the page

I just ran into a problem where I am not sure how to solve.
Background: I've got an App with two views:
1st one to input a number,
2nd one to see the details.
After the view switched to the detail view, I would call the bindElement() to get my data from the backend.
_onRoutePatternMatched: function(oEvent) {
// ...
this.getView().bindElement({
path: "/EntitySet('" + id+ "')"
});
},
Problem is that the ID is quite often the same, hence, the method will call the backend only if the ID is different from the last call.
So I tried to solve the problem by using the following:
this.getView().getModel().read("/EntitySet('" + id+ "')",{
success: function(oData, response) {
that.getView().setModel(oData, "");
}
});
By this, the data is always up to date. But now the binding is a bit different.
Binding with bindElement():
{
"id": "1234",
"propety1": "abc",
// ...
}
Binding with setModel() and id = 1234:
{
"EntitySet('1234')": {
"id": "1234",
"propety1": "abc",
// ...
}
}
For the first way, my binding looked like this:
<ObjectHeader title="{id}">
Now, it would have to look like this:
<ObjectHeader title="{/EntitySet('1234')/id}">
And here I have a problem, because the value of id (in this case 1234) will always be different and so the binding won't work. I can't bind directly to the ObjectHeader, because I will need some properties from the model later. That is the reason I am binding to the view so that all that remain available.
My idea was to edit the binding inside the success method of the read method. I would like to delete the surrounding element. Do you have an idea, how to do this? Or even a simpler/better idea to solve my pity?
Edit:
I forgot to mention the refresh method. This would be possible, but where do I have to put it? I don't want to call the backend twice.
Simply call the API myODataModel.invalidateEntry(<key>) before binding the context in order to retrieve the latest data.
// after $metadata loaded..
const model = this.getOwnerComponent().getModel("odata");
const key = model.createKey(/*...*/) //See https://stackoverflow.com/a/47016070/5846045
model.invalidateEntry(key); // <-- before binding
this.getView().bindElement({
path: "odata>/" + key,
// ...
});
From https://embed.plnkr.co/b0bXJK?show=controller/Detail.controller.js,preview
invalidateEntrydoc
Invalidate a single entry in the model data.
Mark the selected entry in the model cache as invalid. Next time a context binding or list binding is done, the entry will be detected as invalid and will be refreshed from the server.

shouldComponentUpdate won't receive the newest state

I use Reflux.connect methods to change component state, but I can't get the different part in shouldComponentUpdate between nextState and this.state. Actually, this.state already has the new values I was expecting to be in nextState when shouldComponentUpdate is called.
What should I need to do when I want to use shouldComponentUpdate with Reflux?
var component = React.createClass({
mixins: [Reflux.connect(store1, 'store1data'),
Reflux.connect(store2, 'store2data')],
shouldComponentUpdate: function(nextProps, nextState) {
//Here this.state.store1data is equal to nextState.store1data
}
Make sure you're not mutating the state and instead returning a new copy of it. If your store only changes the field inside the state, then the this.state pointer already points to the mutated state.
so in your store1, instead of:
store1Data.someKey = newValue;
this.trigger(store1Data)
try doing:
store1Data = _.assign({}, store1Data, {someKey: newValue}); // this uses lodash, for example
this.trigger(store1Data)
That way you will get a fresh copy of store1Data every time it changes.
Immutability is an important concept when working with states, especially in React/Flux, since it allows you to determine quickly whether a state was changed. Try making a habit of always returning a new copy when changing the state, and to never change to anything inside the state unless you clone it first.
Immutablity in ReactImmutableJs

Breeze and extraMetadata

I have a strange behavior regarding the extraMetadata (I am using OData)
1. I have created a clone function - I am creating new manager and importing into in an entity which I perform the operation
ctor.prototype.clone = function() {
var clonedManager = this.entityAspect.entityManager.createEmptyCopy(),
exportData = this.entityAspect.entityManager.exportEntities([this], true), //export it to the new manager
cloned;
clonedManager.importEntities(exportData);
cloned = clonedManager.getEntityByKey(this.entityAspect.getKey());
return cloned;
};
how ever I had to add
cloned.entityAspect.extraMetadata = this.entityAspect.extraMetadata;
cause I saw that it isn't being exported/imported
when I get entities using expand, those entities don't hold extraMetadata;
and without the extraMetadata I cannot commit the changes - as I get exception
As of BreezeJs version 1.4.13, available now, this has been fixed.

EmberJS, Loading first object on page load

Hopefully, a simple question and must have a simple answer but i have wasted almost 3hrs in getting out of this issue.
I have a user model. I want to load the first user from DB and show it on first page load.
What i am trying to use is:
in my ArrayController,
init: function(){
var user = App.User.find(1)
console.log(user);
this.set('defualtUser',user.get('name'))
}
But i cant get the name of user.
Here is the output of user in console, which indicates that data is being loaded but i can't just get it to use.
Class
__ember1367188634172: "ember270"
__ember1367188634172_meta: Meta
_changesToSync: Object
_data: Object
attributes: Object
***name: "Cafe Alpino"***
__proto__: Object
belongsTo: Object
hasMany: Object
id: null
__proto__: Object
See the name: "Cafe Alpino", i just want to display this name.
Any help???
BTW, i am a newbie with EmberJS
I think the problem here is asynchronousy. This line: var user = App.User.find(1) will result in a user record that is not loaded yet; its properties aren't set until the AJAX call returns in the background. Therefore, user.get('name') will be empty.
There are probably a few ways to solve this. I haven't used Ember Data too much (since it's not very solid at the moment), but according to the docmentation, there should be a didLoad event that you can use:
init: function() {
var user = App.User.find(1);
var _this = this;
user.on('didLoad', function() {
_this.set('defaultUser', user.get('name'));
});
}
Give it a try! Let me know if it doesn't work out.

TFS 2010 API: Get old name/location of renamed/moved item

I'm writing an application that pulls changesets from TFS and exports a csv file that describes the latest changes for use in a script to push those changes into ClearCase. The "latest" doesn't necessarily mean the latest, however. If a file was added and then edited, I only need to know that the file was added, and get the latest version so that my script knows how to properly handle it. Most of this is fairly straight-forward. I'm getting hung up on files that have been renamed or moved, as I do not want to show that item as being deleted, and another item added. To uphold the integrity of ClearCase, I need to have in the CSV file that the item is moved or renamed, along with the old location and the new location.
So, the issue I'm having is tracing a renamed (or moved) file back to the previous name or location so that I can correlate it to the new location/name. Where in the API can I get this information?
Here is your answer:
http://social.msdn.microsoft.com/Forums/en/tfsgeneral/thread/f9c7e7b4-b05f-4d3e-b8ea-cfbd316ef737
Using QueryHistory you can find out that an item was renamed, then using its previous changeset (previous to the one that says it was renamed) you can find its previous name.
You will need to use VersionControlServer.QueryHistory in a manner similar to the following method. Pay particular attention to SlotMode which must be false in order for renames to be followed.
private static void PrintNames(VersionControlServer vcs, Change change)
{
//The key here is to be sure Slot Mode is enabled.
IEnumerable<Changeset> queryHistory =
vcs.QueryHistory(
new QueryHistoryParameters(change.Item.ServerItem, RecursionType.None)
{
IncludeChanges = true,
SlotMode = false,
VersionEnd = new ChangesetVersionSpec(change.Item.ChangesetId)
});
string name = string.Empty;
var changes = queryHistory.SelectMany(changeset => changeset.Changes);
foreach (var chng in changes)
{
if (name != chng.Item.ServerItem)
{
name = chng.Item.ServerItem;
Console.WriteLine(name);
}
}
}
EDIT: Moved the other solution up. What follows worked when I was testing against a pure Rename change but broke when I tired against a Rename and Edit change.
This is probably the most efficient way to get the previous name. While it works (TFS2013 API against as TFS2012 install), it look like a bug to me.
private static string GetPreviousServerItem(VersionControlServer vcs, Item item)
{
Change[] changes = vcs.GetChangesForChangeset(
item.ChangesetId,
includeDownloadInfo: false,
pageSize: int.MaxValue,
lastItem: new ItemSpec(item.ServerItem, RecursionType.None));
string previousServerItem = changes.Single().Item.ServerItem;
//Yep, this passes
Trace.Assert(item.ServerItem != previousServerItem);
return previousServerItem;
}
it would be used like:
if (change.ChangeType.HasFlag(ChangeType.Rename))
{
string oldServerPath = GetPreviousServerItem(vcs, change.Item);
// ...
}

Resources