Backbone view rendering multiple models - backbone.js

I'm playing with Backbone and am getting one model rendered 4 extra times in my list view.
I create and fetch the collection before calling history.start but I don't think that has to do with it.
I'm calling against an api that is only returning 2 models in json. The first model rendered shows up just once and the next shows 5 times in a row. This happens every time.
Here's my code.
https://gist.github.com/3843944

On line 66 you have this line:
#$("div").append(view.render().el)
That gets called each time you render a service provider. Due to the generic selector, div, I think it's selecting every div that exists in the element. When you add the first entry, the only div that exists is <div class='providers'>. However, when it's rendering the second entry it's selecting that div and all new div's created by the first service provider and appended to the template.
Try something like this:
#$el.append(view.render().el)

Related

AngularJS: Accessing the changed class of an element after ng-click

I have applied ng-click on an element and within the function, I want to access the DOM element itself. I could do that with :
var element = $document[1].getElementById('<id of the element>');
However, the problem I am facing is that when that element is clicked, it's class changes. But the element I get using the above method is the previous state of the element before the click. How can I get access to the new attributes of an element after the click is performed ?
Update
I am using AngularJS' smart-table for displaying data fetched from backend. The library offers sort functionality but it sorts the data which is already fetched from the DB and is present in front end. I wanted to tweak it so that when I click the sort button, I should be fetching data from the backend and update the rowCollection so that the table refreshes. Now, in order to trigger the API call, I was thinking of using ng-click event on table headers. Also, I need to know whether I need to sort in ascending order or descending order. So, for that, smart-table automatically appends a class sort-ascent or sort-descent to the table header when it is clicked. So, I thought maybe if I can access that, then using the combination of the header column (sort key) and the class (sort order), I can hit the backend API and fetch the appropriate data.
I understand the solution looks more of a hack then a proper way of doing things.
Maybe you should look at this answer : Accessing clicked element in angularjs
You can access by $event.target
<button ng-click="yourSubmit($event)"></button>

How to make ng-repeat update view on condition only

Say I have an ng-repeat directive and it displays some data in the table.
When I press a button I send the $http API call to the server and it responds with the new data which is displayed in the same table with a little delay.
I would like ng-repeat to re-render the table view only after this new data has finished loading. But as of now I can see how ng-repeat shows an empty table for a moment and only after that the new data is fetched.
So the question is how does one make Angular update the ng-repeat only on a condition? The event that is fired when the data has finished loading can be an example of such condition.
P. S. I tried prefixing my array with ::, but of no help. It prevented Angular from instant updating the view, but I don't know the way to force the update when I want to.

Where to put a function to create a pdf

I have an application which deals with projects evolving according to a process defined by a series of status transitions. I have a button to set a project to the next status. The button calls a function in the ProjectsController. This function calls another function in the Project model, where I search for the correct transition, depending on the current status, the user_group and some other parameter, and set the new status. After everything successfully accomplished, I return to the original page with 'return $this->redirect($this->referer());' from the controller.
Some of the transitions have side effects. One is to create a PDF, save it on the server and add a new entry to the 'documents' table referenced to the current project.
Problem: where should I put the function to create the PDF? I would like to put it to the Model. But I need some View Files to first render a html page and then convert it to the PDF. I could put it to the Controller. But then I have a controller function which should not be called directly an doesn't render a view.
The functions all work, but where to put them? Is there another possibility? Would it be possible to use a component?
Implement it as PdfView that will render any (pdf) view for you as Pdf. There is already a plugin that does this, search for CakePdf on Github.
A component is clearly the wrong place. A Pdf is output, so it's a kind of view. Model gets you the data, controller sets it, view renders it.

AngularJS: ng-model not getting applied on Controller instantiation

I am creating a web app planner using Angular and I am having some difficulties with a <select> box that is not changing value based on the variable denoted with ng-model.
My architecture is as follows:
I am using ui-router which gives me different view states, one for each page of my planner. The root HTML page has a Controller called MainController. This is where I set up my JSON model, $scope.Master = {} that I want to use throughout the planner. All pages of the planner should inherit this model and continue to modify/add to it.
I then have my 4 pages of the planner like:
Start -> Accounts -> Settings -> Review
Each page has its own Controller that gets instantiated every time I visit the page. On the Start page, I have a <select> box that has ng-model="$scope.Master.Start.selectedAccount" that gets populated dynamically using the StartController (therefore it gets populated every time I come to the Start page).
This <select> works great on the first time to the page, but if I go to Accounts and then come back, the select box is back to the default value, "Please select an account", instead of the selected account that is in the $scope.Master.Start.selectedAccount model that is bound to the <select> box
I thought I could just do something like $scope.$apply or something in order to re-apply the binding to the DOM object, but that just gave me an error saying it is already digesting.
How can I apply the binding to the <select> box after the page has been loaded 2 or more times?
This is probably because every time you go back to your original page, a new controller is instantiated since it was removed from the DOM when you left it originally. Thus $scope.Master.Start.selectedAccount. To save this, you can either
Use a service / factory singleton on the main app to save this value
https://docs.angularjs.org/guide/services#!
Save $scope.Master.Start.selectedAccount as a global variable
https://docs.angularjs.org/api/ng/service/$rootScope
Put that controller on the outside
Im real sorry... I realized I was populating the <select> using ng-repeat instead of ng-options no idea how I managed that... That was the problem

Forcing Object Data Source To Reinstantiate

I am using the XPages Mobile Controls with an Object data source (Java Class which is NOT a managed bean) tied to View scope on a second app page. I have resetContent on the second page set to true. So I would have assumed the Object Data Source would be destroyed and recreated every time I transitioned to the second page.
When I transition to the second page the first time, the createObject() method is invoked as expected. If I transition to the second page using a button AND set forceFullRefresh to true the createObject() method is invoked. If, however I have a Rounded List Item with a moveTo specified for the second page the createObject() method does not get invoked. Instead the object remains set to the last value it was using when that application page was last accessed.
Is there a way to force the createObject() method to be invoked every time I transition to the page?
Another way is to call the refresh method of the datasource in SSJS.
Assumning you have only one datasource on the page, you can access the ObjectDataSource from the view:
var ods:com.ibm.xsp.extlib.model.ObjectDataSource = view.getData().get(0);
ods.refresh()
This executes the createObject method binding and reinstantiate the datasource.
The solution turned out to be to move the object data source from view scope to request scope. This is possible because I do not have the need for any partial refreshes on that page until the details are ready to be submitted.

Resources