Emberjs linkTo doesnot update collection i.e department.find() - ember.js

Learning emberjs
I am not sure if this is a stackoverflow question or git issue. So I decided to put it on stackoverflow first.
Here is my Jsbin (Open in firefox ..not in chrome as raw.github file is used)
When I click on "<- All Department" in department template which I reached after creating a new department it does navigate back to departments template
but the #each does not display the newly added department name in list.
It does show the newly added department on refreshing the browser on /departments

UPDATE
It seems that the .set() method is working but for some reason the new object created is returning the name and ID as undefined. Might be a bug with ember-model perhaps.
The best solution for the moment would be to have 2 save methods, one on the edit controller as you currently do and then adding a different save method for creating a new department.
App.NewController = Ember.ObjectController.extend({
save:function(){
var newDep = App.Department.create({name: this.get('name')});
newDep.save();
this.get('target').transitionTo('department', this.get('model'));
}
});
Here is a jsbin with the New controller added - http://jsbin.com/EVUlOyo/1/edit
End Update
It looks like when you are creating the record it is not setting the name value correctly on the object.
I changed the following -
newDepartment = self.get('model');
newDepartment.set('name',this.get('name'));
newDepartment.save();
to -
var newDep = App.Department.create({name: this.get('name')});
newDep.save();
Here is an updated jsbin also http://jsbin.com/EkEXInO/1/edit
Hope that helps and works for you.

Related

Updating and creating a new instance at the same time

When a user updates an invoice form, i want to create a new invoice record with the updated attributes, but also change one or two fields of the old record and save it, too.
How would the outline of a controller action look like which could accomplish this?
Instead of a controller action i put the code in the model, using callbacks:
before_save do |rec|
if !rec.new_record?
attrb = rec.attributes.delete_if{|k, v| ["id"].include? k }
Book.create(attrb)
rec.restore_attributes
rec.year = rec.year + 2 # some custom change
true
end
end
I keep all attributes unless the 'id' (otherwise i get an error) for create a new record with the new attributes.
Then i restore the attributes of the existing record. I do some custom change before saving.
I am rather new with Rails but this seems pretty straightforward. As you mention the user is 'updating" an invoice, your controller view has probably been passed all the data available to the user for further change.
When submitting the form, your update action can easily update the current record data, as well as creating a new one on top of this
Though as it is automated, you need to make clear:
if a new invoice record is created each time an invoice record is
updated (thi can create a lot of copies of the same invoice)
how you make the old record an archive to avoid duplicates
can the 'additional" amendments be automated and easily processed through an algorithm...
Nested attributes made things a bit tricky. So in order to create new instances I had to use the dup method for both the resource and its nested items.
Generally, it is advisable to keep the controllers slim and make the models fat. Nevertheless, I have decided to include this code into my Invoices controller:
def revise_save
#contact = Contact.find(params[:contact_id])
#invoice = #contact.invoices.find(params[:invoice_id])
#invoice_old = #invoice.dup
#invoice.invoice_items.each do |item|
#invoice_old.invoice_items << item.dup
end
#invoice.datum = DateTime.now.to_date
# archive old invoice
# #invoice_old. ...
#invoice_old.save
# make old new invoice
#invoice.datum = Time.now
# ...
#invoice.update(invoice_params)
redirect_to invoices_path
end
Note that in this solution the currently edited (original) invoice becomes the new invoice, the old one is paradoxically created anew.
Thanks to #iwan-b for pointing me in the right direction.

Dynamically add js object to model array in 1.13

I have the following code:
var msg = this.store.createRecord({text:'first title', createdAt: "2015-06-22T20:06:06+03:00" })
this.get('model.content').pushObject(msg);
msg.save();
We create new record. Then push in it to the model to display. It worked perfectly in 1.9 version but after upgrading it to the newest 1.13 it breaks and shows this error:
TypeError: internalModel.getRecord is not a function
after some researches I came out to this solution
this.get('messages.content').unshiftObject(message.internalModel);
and it partially help. Now I have two problems:
I'm not confident if using private ember data api is a good idea
I have an annoying delay between adding record to the model and
rendering it on the screen. More than that if I don't call
msg.save(); the record isn't rendered. So as far as I understood it
waits until we have response from server and only then renders it.
But I need opposite behaviour - I need to show the record first and
then save it(showing the saving state for the user), this way user
thinks that everything goes extrimely fast.
One possible solution without resorting to private API is to use toArray() (github issue):
var array = this.get('messages').toArray()
array.addObjects(this.get('messages'))
array.addObject(msg)
this.set('messages', array)
Before 1.13:
this.get('content').pushObjects(messages);
After 1.13:
messages.forEach(functio(message) {
this.get('model.content').pushObject(message._internalModel);
});
I would make all return models to array then, add array to this array
setPeople:function(){
this.set('people',this.get('content').toArray())
}.observes('content')
then, find more person models, to array
getMoreUsers(){
var self = this;
this.set('offset', this.get('offset')+1);
self.store.findAll('person').then(function(people){
self.get('people').pushObjects(people.toArray());
});

Update URL after model is modified

I have a route like this "loans/:loan_id", from a link I redirect to this URL and send an unsaved Loan object as model, so the id is null, which results in the url being "loans/null", however I then save the model and it gets an ID from the server, but how can I update the URL so that it shows the new ID instead of null?
Thanks.
I assume you have a LoanNewController or something similar. Then I further assume that you are trying to transition to the new created loan object directly after you have created it, this will show an id of null since the create loan action is async and you have to wait for the loan to be created on the backend before you do the transition, so in order for it to work you could do the following:
App.LoanNewController = Ember.ObjectController.extend({
saveLoan: function() {
...
this.get('store').commit();
},
...
transitionAfterSave: function() {
if(this.get('content.id')) {
this.transitionToRoute('loan', this.get('content'));
}
}.observes(content.id)
The added observer will observe the content.id and when it is set (when the server call has returned) the transitionAfterSave will be invoked and the transition will get the content passed to it with the correct id in place.
This answer is based mainly on assumptions, since you didn't reveal that much code, but you get the point I guess.
Hope it helps.

Sitecore Web Forms for Marketers and DMS - not recording campaigns, goals and dropout info

In WFFM there is an option so that, when someone abandons the form, any data that was entered in the form itself is recorded and should be accessible via the Dropout Report.
I have a WFFM for which I have turned on Analytics and turned on the dropout feature. Unfortunately I don't see any data being recorded in the DB and the Dropout Report is visible, but empty.
I see from the javascript code included in the WFFM folder that a series of AJAX calls are supposed to save the fields on blur events -- with calls to /sitecore modules/web/Web Forms for Marketers/Tracking.aspx
I tried debugging the Javascript code, but the method supposed to post the info to /sitecore modules/web/Web Forms for Marketers/Tracking.aspx is never being called. Can you think of any reasons for this code not to work? Also, does anyone know which table this information is supposed to be recorded? Is it the fields table in the WFFM DB?
Finally, even though I have turned on analytics on this particular WFFM form and I have associated a campaign and a goal to the submission of the form, none of these is being recorded. I see that the data entered in the form is stored successfully and is displaying in the Data Report, but no info about the Campaign nor the Goal are recorded in the DB.
I even checked manually directly in the DMS DB running:
select top 10
p.DateTime, p.UrlText, cp.CampaignName
,i.Url, vi.VisitId
from pages p
inner join ItemUrls i on p.ItemId = i.ItemId
inner join Visits vi on vi.VisitId = p.VisitId
inner join GeoIps g on vi.Ip = g.Ip
left join Campaigns cp on cp.CampaignId = vi.CampaignId
order by p.DateTime desc
This one shows that the page where the form is rendered is being hit, but no campaign is associated to the visit.
Then I tried the following:
select pe.datetime, ped.Name, pg.UrlText from PageEvents pe
inner join PageEventDefinitions ped on ped.PageEventDefinitionId = pe.PageEventDefinitionId
inner join Pages pg on pg.PageId = pe.PageId
order by pe.DateTime desc
But I don't see any entry for this particular campaign nor for the goal (while I see entries for other campaigns and goals associated to non-WFFM Sitecore items)
Any advice would be greatly appreciated!
Thanks,
Francesco
EDIT
The sc.webform.js file contains this method:
_create: function () {
var self = this,
options = this.options;
if (options.tracking) {
this.element.find("input[type!='submit'], select, textarea")
.bind('focus', function (e) { self.onFocusField(e, this) })
.bind('blur change', function (e) { self.onBlurField(e, this) });
this.element.find("select")
.change(function () { $scw.webform.controls.updateAnalyticsListValue(this) });
this.element.find("input[type='checkbox'], input[type='radio']")
.click(function () { $scw.webform.controls.updateAnalyticsListValue(this) });
}
this.element.find(".scfDatePickerTextBox").each(function () { $scw.webform.controls.datePicker(this) });
},
This is supposed to be called by the form on sc.webform widget initialization. It should bind the focus and blur change events for all input fields, drop downs and text areas. Unfortunately, when I tried to put a break point inside this method, it never gets called.
SECOND EDIT
Interesting. I figured out that the whole thing should start from this line of Javascript code embedded in the page that contains the WFFM form:
<script type="text/javascript">
$scwhead.ready(function() {
$scw('#form_A8BF483419174F97A2830E12CBCF7E4F').webform({formId: "{A8BF4834-1917-4F97-A283-0E12CBCF7E4F}",pageId: "{21C24144-B964-4FBA-8388-D9B90EBBC17C}",eventCountId: "pagecolumns_0_columncontent_0_bottomrow_0_form_A8BF483419174F97A2830E12CBCF7E4F_form_A8BF483419174F97A2830E12CBCF7E4F_eventcount",tracking: true})
});
</script>
Once I put a break point here, I was finally able to trace into the _create method of the jQuery.UI widget defined in sc.webform.js. The code that calls _create is actually inside the jQuery.UI library. Kinda makes sense, right?
Finally, the code inside _create is executed, the blur events are bound to the TrackEvents method, also defined within the widget:
_trackEvents: function(events) {
$scw.ajax({
type: 'POST',
url: "/sitecore modules/web/Web Forms for Marketers/Tracking.aspx" + location.search,
data: {track: JSON.stringify(events)},
dataType: 'json'
});
What doesn't make sense is that now, even though I can finally see trackEvents being called whenever I tab from field to field in the WFFM form (why wasn't working before it's a mistery to me), I don't see any data recorded in the WFFM DB. I even tried a quick query in the DB:
select f.Timestamp, f.StorageName, fi.Value, fi.FieldName
from Form f
inner join Field fi on f.Id = fi.FormId
order by f.Timestamp desc, FieldName
Does anybody know where is Tracking.aspx supposed to save the captured field informations?
This may be silly to ask, but did you configure the data source correctly for your WFFM? I mean, obviously, you're using WFFM..but is it set to use SQL or is it using the "file" that WFFM uses by default as it's database.
like this to use SQL:
<!-- MSSQL-->
<formsDataProvider type="Sitecore.Forms.Data.DataProviders.WFMDataProvider,Sitecore.Forms.Core">
<param desc="connection string">Database=Sitecore_WebForms;Data Source=xxx;user id=xxx;password=xxx;Connect Timeout=30</param>
</formsDataProvider>
<!-- SQLite -->
<!--<formsDataProvider type="Sitecore.Forms.Data.DataProviders.SQLite.SQLiteWFMDataProvider,Sitecore.Forms.Core">
<param desc="connection string">Data Source=/data/sitecore_webforms.db;version=3;BinaryGUID=true</param>
</formsDataProvider>-->
If you don't configure that correctly, I'm wondering if somehow data is being recorded in one place but not another? Also, another question I have is to ask if this is a dev environment, are you running webforms in live mode? It just seems to me like this is a configuration issue.
We are experiencing the exact same problem on 6.5 update 6 and WFFM 2.3.3 rev. 111209. We can see the asynchronous calls to the server including the probably well formed json object containing the correct event.
Example:
track:[{"fieldId":"{E0A0BCDD-85E1-4D8D-9E76-5ABD240423C9}","type":"Field Completed","value":"test","formId":"{0F3B57C1-1B6A-43B9-A5A6-2E958C168B31}","pageId":"{025AFF68-62B9-42CE-B49F-0C36311E1976}","ticks":16}]
We don't see any of the dropouts arrive in the database, though...
Have you made sure your campaigns and goals have been deployed? If you have switched databases they may not be. To redeploy do this:
For each Goal in System -> Marketing Center -> Goals
Change the workflow state to draft
Save
Then in the review ribbon click deploy.
This will create an entry in the pageeventdefinition table and allow
you to query.
Don't forget to do the same for campaigns.

Django, Tastypie and retrieving the new object data

Im playing a little bit with heavy-client app.
Imagine I have this model:
class Category(models.Model):
name = models.CharField(max_length=30)
color = models.CharField(max_length=9)
Im using knockoutjs (but I guess this is not important). I have a list (observableArray) with categories and I want to create a new category.
I create a new object and I push it to the list. So far so good.
What about saving it on my db? Because I'm using tastypie I can make a POST to '/api/v1/category/' and voilĂ , the new category is on the DB.
Ok, but... I haven't refresh the page, so... if I want to update the new category, how I do it?
I mean, when I retrieve the categories, I can save the ID so I can make a put to '/api/v1/category/id' and save the changes, but... when I create a new category, the DB assign a id to it, but my javascript doesn't know that id yet.
in other words, the workflow is something like:
make a get > push the existing objects (with their ids) on a list > create a new category > push it on the list > save the existing category (the category doesnt have the id on the javacript) > edit the category > How I save the changes?
So, my question is, what's the common path? I thought about sending the category and retrieving the id somehow and assign it to my object on js to be able to modify it later. The problem is that making a POST to the server doesn't return anything.
In the past I did something like that, send the object via post, save it, retrieve it and send it back, on the success method retrieve the id and assign it to the js object.
Thanks!
Tastypie comes with an always_return_data option for Resources.
When always_return_data=True for your Resource, the API always returns the full object event on POST/PUT, so that when you create a new object you can get the created ID on the same request.
You can then just read the response from your AJAX and decode the JSON (i dont know about knockout yet).
see the doc : http://readthedocs.org/docs/django-tastypie/en/latest/resources.html?highlight=always_return_data#always-return-data
Hope this helps