I'm learning both CoffeeScript and Backbone JS. I want to load just one piece of equipment. Yes, I know I don't need Backbone JS for this - But it helps me to learn if I start with basics. As soon as the page loads, I want it to grab some JSON from the server, and display it on the page.
Here is my coffeescript so far:
jQuery ->
class Equipment extends Backbone.Model
defaults:
title:''
desc:''
url:'/getData'
class ItemView extends Backbone.View
tagName: 'div'
initialize: ->
_.bindAll #, 'render'
render: ->
$(#el).html """
<h1>#{#model.get 'title'}</h2>
<p>#{#model.get 'desc'}</p>
"""
#
class AppRouter extends Backbone.Router.extend
routes:
'':'getData'
getData: ->
#equipment = new #Equipment()
#equipmentView = new #ItemView
model: #equipment
#equipment.fetch()
$('div').html #equipmentView.render().el
appRouter = new AppRouter
Backbone.history.start()
I feel like I have all the pieces in place, and am getting no errors (either in compilation or running the page).
The basic JSON I expect back from the server is just a PHP page echoing this:
{
"title": "title",
"desc": "description"
}
What am I missing?
Does #equipment.fetch() even trigger a HTTP request?
To my understanding you must set the id: #equipment = new #Equipment(id:123) which would trigger a "/getData/123" request.
or specify the url in the fetch: #equipment.fetch(url:"/getData") to load
But then the view would still be empty, because the data isn't yet loaded when the View render() is executed. Backbone doesn't automatically update views when models change (Like EmberJS does).
Add #listenTo(#model, "change", #render) to the initialize method to re-render when the model changes.
I found a nice guide/tutorial for you
http://adamjspooner.github.com/coffeescript-meet-backbonejs/
You have to tell Backbone to route your initial url ('') like this :
Backbone.history.start pushState: true
You also should pass an id (I think Backbone will request /getData/undefined in your case and on a side note I think you should use coffee's fat arrows instead of bindAll (it's one of the many great thing about coffeescript, but then you should get rid of some of the #s because they won't refer to window anymore...
Related
Although I feel this answer is relatively close to my problem and got some reputation, I don't get it right. I read a lot of posts on how to use the "new" style of Observer-pattern ((...).pipe(map(...)).subscribe(...) and *ngFor="... | async") in Angular and now also stumbled across How to Avoid Observables in Angular. I don't want to avoid reactive behaviour; I want to have changes in the REST-API to be reflected "live" to the user without reloading the Observer. That's why I want to subscribe an object (and therefore also its properties) to an Observable (and the 'might-be-there' values from the data-stream in it), right?
In my template I have:
<p>Werte:<br><span *ngFor="let attribute of _attributes | slice:0:5; index as h">
{{attribute.name}}: <strong>{{getParamNameAt(h)}}</strong> </span><br>
<span *ngFor="let attribute of _attributes | slice:5: _attributes.length; index as h">
{{attribute.name}}: <strong>{{getParamNameAt(h + 5)}}</strong> </span></p>
In my component I have:
private _attributes: Attribute[];
constructor(private attributesService: BkGenericaAttributesService) {
attributesService.getAttributes().subscribe({ next: attributes => this._attributes = attributes });
}
getParamNameAt(h: number): string {
let attrVal = this.bkHerstArtNr.charAt(h);
return attributes[h].subModule.find(param => param.subModuleValue === attrVal).subModuleName;
}
and as service I have:
const localUrl = '../../assets/json/response.json';
#Injectable()
export class BkGenericaAttributesMockService implements BkGenericaAttributesService {
constructor(private http: HttpClient) {
}
getAttributes(): Observable<Attribute[]> {
return this.http.get<Attribute[]>(localUrl).pipe(
tap((attributes : Attribute[]) => attributes.map((attribute : Attribute) => console.log("Piping into the http-request and mapping one object after another: " + attribute.name))),
map((attributes : Attribute[]) => attributes.map((attribute : Attribute) => new Attribute(attribute.id, attribute.name, attribute.title, attribute.description,
(attribute.parameters ? attribute.parameters.map((parameter : Parameter) => new Parameter(parameter.id,
parameter.name, parameter.value)) : [])))));
}
My problem running the application at this point is the 'to-create-on-stream' Attribute-objects and "nested" Parameters[]-array (created by pushing Parameter-objects into it) pushed into the _attributes-array from the httpClient's Observable: Piping into the http-request and mapping one object after another: undefined.
Apart from this - is my construct the right way to read values from a JSON-file (or alternatively an API-stream, which may change while a user visits the SPA) into properties of multiple objects displayed on the Angular view?
With the answer mentioned above - or the way I thought I have to translate it into my code - I start to doubt that I'm really understanding (and using) the reactive Angular way with Data-Providers <= Observables => Operators => Subscribers and finally Observers displayed to the user.
I really am confused (as you can read), because a lot of answers and descriptions that I found so far use either older patterns (before Angular 5.5?) and/or partially contradict each other.
Do I handle the API-changes in the right place? Has the array for the template's *ngFor-directives to be an Observer (handled with | async) or will the changes of respectively within the array be handled by the model behind the template and the template grabs its new values (with interpolation and property binding) and also directives with a change in the components properties without asyncing?
Briefly:
Is there a for-dummies default instruction to "stream-read" values from a http-request into multiple Typescript-objects and their properties concurrently displayed in a template with on-stream-changing directives rendered only in the relevant DOM nodes, the Angular 8 opinionated way? "Stream-reading" meaning: pulling and pushing (only) if there are changes in the API, without wasting resources.
If I understand right, you want the server to push changes to the client, as soon as they happen, so that the client can react and render accordingly, right ?
this.http.get is a single call, that will resolve with a snapshot of the data. Meaning that it won't automatically update just because some data changed in your backend.
If you want to notify the client about new data or even send that data directly to the client, you'll need websockets.
There is also some problems with code:
if you .subscribe(), you'll need to .unsubscribe(), otherwise you'll end up with a memory leak.
param => param.value === attrVal, where is attrVal coming from, I don't see it being set aynwhere in the method ?
You should use the async pipe, as it unsubscribes automatically for you.
You don't neet to create class instances via new in your service, instead your Attribute typing should be an interface.
i want to map a Route to an ApiController, to post data to it.
I'm not using a Surface contoller, since i want a clean url like /api/test/{action}, without the umbraco/surface part in url.
I'm trying to use
RouteTable.Routes.MapHttpRoute(
"ApiTest",
"Api/Test/{action}",
new
{
controller = "Api_Test",
action = "Search"
});
But i'm getting an error since MapHttpRoute need a 4th string[] parameter.
How can i Map that route?
Then i will post a json or xml and return the response (json or xml).
Use RouteTable.Routes.MapRoute instead. I've used that previously in Umbraco sites and it works fine, e.g.
RouteTable.Routes.MapRoute(
name: "cookie-api-location",
url: "cookie-api/setregioncheckcookie/",
defaults: new
{
controller = "Cookie",
action = "SetRegionCheckCookie"
}
);
I have an Ember app consuming a rails based webservice.
On the Rails side, I have some enums, they are simply arrays.
Now, I would like to retreive those enums in the Ember app, and render them for select values.
The webservice returns a JSON response :
get '/grades.json'
{"grades":["cp","ce1","ce2","cm1","cm2"]}
On the Ember side, I created a GradesRoute like this :
App.GradesRoute = Ember.Route.extend({
model: function () {
return Em.$.getJSON('api/v1/grades.json')
}
}));
Then, I think I need it in the controllers where these enums are in use:
App.StudentsController = Ember.ArrayController.extend({
needs: ['grades'],
grades: Ember.computed.alias('controllers.grades')
}
));
So at least I thought I could iterate over the grades in the students template.
{{#each grade in grades}}
{{grade}}
{{/each}}
But I get no output at all... debugging from the template and trying templateContext.get('grades').get('model') returns an empty array []
Any idea on how I could load and access this data ?
So I ended up with ApplicationRoute, which is the immediate parent of StudentsRoute, so needs is relevant in this case.
App.ApplicationRoute = Ember.Route.extend({
setupController: function(controller) {
Em.$.getJSON('api/v1/enums.json').then(function(data){
controller.set('grades', data['grades']);
controller.set('states', data['states']);
}
}
});
Now I can create an alias for each enums I need to use accross my app.
App.StudentsController = Ember.ArrayController.extend({
needs: ['application'],
grades: Ember.computed.alias('controllers.application.grades'),
states: Ember.computed.alias('controllers.application.states')
});
I'm still not confident enough to be sure this is the way to go, any suggestion is welcome !
You just have some of your paths mixed up. In StudentsController, controllers.grades refers to the actual controller, not it's model. The following code should clear things up as it's a bit more explicit in naming.
App.StudentsController = Ember.ArrayController.extend({
needs: ['grades'],
gradesController: Ember.computed.alias('controllers.grades'),
grades: Ember.computed.alias('gradesController.model.grades')
});
Also, be aware that using needs only works if your grades route is a direct parent of your students route. If it's not a direct parent, you won't get back the data you want.
I have a controller that uploads and processes a file. Afterwards, I wish to render the processing result in a modal div. I wanted to know what the best way is to get the results from the controller to the modal div on the gsp. I thought about a template but I didn't know how to specify what the target div for the template should be because this template wouldn't be rendered by a button click where a target for template render is set as an attribute, it would be done on a timed basis (i.e. when the file is done uploading). The other way is to send JSON back from the controller but I don't know how to intercept this JSON at the right time because I still don't quite understand the timings of the information flow between the GSP and the Controller. I know how to send the JSON but how to alert the GSP that "hey, some JSON is now ready for your modal that's about to go up." Here is some pseoducode of basically what I am trying to get done.
Controller:
upload() {
// process file and store results in three integers
// int1 = result1
// int2 = result2
// int3 = result3
// send the three numbers to the gsp
}
Now what is the best way to get these three numbers to the GSP so that they are displayed on a modal dialog which is about to go up like this:
<div id="fileUploadResultsModal">
Results:
${int1}, ${int2}, ${int3}
</div>
Here is the JS associated with my ajax upload function:
$("#chseFile").upload("${createLink(controller: 'customer', action: 'upload',)}",
{dataTypegrp: parseInt(getCheckedValue(document.getElementsByName('dataTypegrp'))),
fileTypegrp: parseInt(getCheckedValue(document.getElementsByName('fileTypegrp')))},
function(success) {
$("#cancel1").trigger("click");
setTimeout(function(){
$("#summary").trigger("click");
}, 250);
displaySuccess(data);
},
function(prog, value) {
console.log(value);
$("#prog").val(value);
if (value == 100) {
$("#prog").hide();
$("#progressbar").html("Uploading and processing. Please wait...");
}
});
but right now JS complains that 'data' is not defined. 'data' is meant to be the JSON coming back from the controller.
Thanks
you can render them as JSON:
render( [ int1:111, int2:222, int3:333 ] as JSON )
or as a HTML-string
render "<div id=\"fileUploadResultsModal\">Results:${int1}, ${int2}, ${int3}</div>"
or use a template
render template:'/yourController/templateName', model:[ int1:111, int2:222, int3:333 ]
or a TagLib
render g.yourResultTag( int1:111, int2:222, int3:333 )
For this tiny bit of information, the performance is not of concern. It's rather a matter of taste, or what is more appropriate for your client.
If the later is JSON-biased, use JSON-rendering. If it has a mix of JSON and HTML, use others.
inside controller at the enf of controller action you can use
render [data:['name':'firstname','surname':'secondName'] as JSON]
this will render the data to GSP
I need to load JSON data into a Tree or TreePanel.
The JSON data does not come from a file or retrived from a URL but is built on the fly.
I cannot find any examples.
Can anyone help?
While I was trying to create a Treegrid afetr searching something in a search filed (need to pass this in the URL) i found some strange behaviour.
How I created here is the logic:
Created a Tree class with rootVisible: false and store:mystore
My store has no proxy{} as I had to set this dynamically from controller
Inside the store autoLoad:false was there
Used mystore.load() to load the data into tree
Request was going for 2 times
A blank root node in the tree although I have no root node.
I fixed it in the following way... not sure to wat extend this is correct. Any better solution please share
Tree class(View)
Didn’t define any treestore inside tree view
rootVisible: false
Inside the controller
search: function(button){
var searchText = this.getSearchField().value;
//created a store instance
var mystore = Ext.data.StoreManager.lookup('MyTreeStore');
mystore.setProxy({
type: 'ajax',
url: 'app/searchid/'+searchText;
});
var mytree = Ext.create('AM.view.MyTree',{store:mystore});
Ext.getCmp('tn').add(mytree);
//DON’T USE store.load() method As we have set rootVisible: false so it will automatically try to load the store or will send the request
}
Store file
Ext.define('AM.store.BomTreeStore', {
extend: 'Ext.data.TreeStore',
model: 'AM.model.BomTree',
autoLoad: false,
folderSort: true
});
Any better solution to this plz share :)
You can do it by progammatically creating a root node.
Iterate through your data and keep appending child nodes to your root node.
It has been explained quite well here:
ExtJS: How to create static and dynamic trees