AngularJS Filter Data Binding - javascript

I have a custom filter that I use to return an html string using $sce.trustAsHtml. In the template/view I use ng-bind-html directive and pass the filter to as follows:
<div ng-bind-html="userAgent | geoCode:business"></div>
Inside my filter I have an inner function that takes an input, business model in my case, which takes properties from the business model, a mongoosejs model, and generates a formatted string which is used to generate and html a tag:
'<a href="some_url_i_create" ...>'+ myFormattingInnerFunction(business) +'</a>';
What is strange is, if I use this function several of the fields are returned as undefined/blank. However, if I directly access the variables a follows:
'<a href="some_url_i_create" ...>'+ business.prop1 + business.prop2+ ... +'</a>';
Then all of the properties are found and output. Any ideas?
P.S. The model is a retrieved via an AJAX request, which in turn use mongoosejs to retrieve the data, inside of the angular controller for this section.

When you are calling the function you are accessing the business object on the first rendering event when all the scripts are loaded and the first DOM manipulation occurs.
But When you accessing the business object directly angular puts the values into the view on the first rendering event and on all of the digest events and of course on other rendering events.
You might want to consider using a $scope. attr in the template to render and call the formated string value method in the callback as well.
In the JS:
.success(function(data){
business=JSON.parse(data);//Iguess
$scope.formatedtext= myFormattingInnerFunction(business);
$scope.$apply();// If you use an angular libs callback this probably not needed.
})
In the template:
'<a href="some_url_i_create" ...>'+ formatedtext +'</a>';

Related

Reading OData contexts in onInit of controller

I've tried to prepare data from an OData source to show it in a bar graph in my fiori app. For this, I setup the OData model in the manifest.json. A test with a list, simply using
items="{path : 'modelname>/dataset'}
works fine and shows the content.
To prepare data for a diagram (VizFrame), I used the onInit() function in the controller of the view (mvc:XMLView). The data preparation is similar to the one discussed in question.
At first I obtain the ODataModel:
var oODataModel = this.getOwnerComponent().getModel("modelname");
Next I do the binding:
var oBindings = oODataModel.bindList("/dataset");
Unfortunately, the oBindings().getContexts() array is always empty, and also oBindings.getLength() is zero. As a consequence, the VizFrame shows only "No Data".
May it be that the data model is not fully loaded during the onInit() function, or do I misunderstand the way to access data?
Thanks in advance
Update
I temporary solved the problem by using the automatically created bind from the view displaying the data as list. I grep the "dataReceived" event from the binding getView().byId("myList").getBindings("items") and do my calculation there. The model for the diagram (since it is used in a different view) is created in the Component.js, and registered in the Core sap.ui.getCore().setModel("graphModel").
I think this solution is dirty, because the graph data depends on the list data from a different view, which causes problems, e.g. when you use a growing list (because the data in the binding gets updated and a different range is selected from the odata model).
Any suggestions, how I can get the odata model entries without depending on a different list?
The following image outlines the lifecycle of your UI5 application.
Important are the steps which are highlighted with a red circle. Basically, in your onInit you don't have full access to your model via this.getView().getModel().
That's probably why you tried using this.getOwnerComponent().getModel(). This gives you access to the model, but it's not bound to the view yet so you don't get any contexts.
Similarly metadataLoaded() returns a Promise that is fullfilled a little too early: Right after the metadata has been loaded, which might be before any view binding has been done.
What I usually do is
use onBeforeRendering
This is the lifecycle hook that gets called right after onInit. The view and its models exist, but they are not yet shown to the user. Good possibility to do stuff with your model.
use onRouteMatched
This is not really a lifecycle hook but an event handler which can be bound to the router object of your app. Since you define the event handler in your onInit it will be called later (but not too late) and you can then do your desired stuff. This obviously works only if you've set up routing.
You'll have to wait until the models metadata has been loaded. Try this:
onInit: function() {
var oBindings;
var oODataModel = this.getComponent().getModel("modelname");
oODataModel.metadataLoaded().then(function() {
oBindings = oODataModel.bindList("/dataset");
}.bind(this));
},
May it be that the data model is not fully loaded during the onInit()
function, or do I misunderstand the way to access data?
You could test if your model is fully loaded by console log it before you do the list binding
console.log(oODataModel);
var oBindings = oODataModel.bindList("/dataset");
If your model contains no data, then that's the problem.
My basic misunderstanding was to force the use of the bindings. This seems to work only with UI elements, which organize the data handling. I switched to
oODataModel.read("/dataset", {success: function(oEvent) {
// do all my calculations on the oEvent.results array
// write result into graphModel
}
});
This whole calculation is in a function attached to the requestSent event of the graphModel, which is set as model for the VizFrame in the onBeforeRendering part of the view/controller.

Typeahead in ASP.net MVC

The first image shows that the method I created in user class.
The second image shows the controller that I created. How I take the data from GetGroupManagerAndFranchiseConsultantList? What should I need to write within view?
Right now you are returning Json. So I assume you are calling this call from something like this
<script>
$.getJSON("/Search",function(data){
// data is a JS OBJECT of your JSON data.
});
</script>
If you were looking to use MVC Views you need to return it as a view and use the built-in model binding.

How to trigger function after render template

I am using marionette in my application. I am showing ItemView through regions like in the following.
var productInfoViewObj=new productInfoView.ProductInfoView({model:tagInformationModel.tagInformationModelObj});
exports.MyApp.bodyContainer.show(productInfoViewObj);
This is the code, I written inside view.
exports.ProductInfoView=Backbone.Marionette.ItemView.extend({
domInfo:{
mainTemplateId:"tagProductListTpl",
tableTemplateId:"taginfoViewTpl",
tableContentDiv:"taginfoViewDiv",
//tad Info
tagInfoTabId:"tagInfoBtn",
productInfoTabId:"productInfoBtn"
},
template:function(){
return commonFunctions.templateCompilation("tagProductListTpl","");
},
onRender:function(){
console.log(document.getElementById("productInfoBtn"));
}
});
I am passing templateId and data as arguments to commonFunctions.templateCompilation. It will compile and return compiled string. That compiled result passing to template.
As per my assumption, after completion of template, onRender function will trigger. What I mean before onRender, dom will available whatever we are templating using template.
But I am getting null inside onRender function.
I want a callback, it should trigger after template available in dom. so I can access elements whatever I templated using template.
I can do one thing, whatever I written inside onRender, I can setup time like in the following way.
onRender:function(){
setTimeout(function(){console.log(document.getElementById("productInfoBtn"));},1000);
}
If I set time, working fine but it's not correct way to implement.
can anyone help me.
Thanks.
It's resolved, I have to use onShow instead of onRender function. Now it's working fine.

populating Moustache.js template

I am currently working with a QuickBase database trying to make a custom report using moustache.js, When I was looking into moustach.js I noticed you needed to have your data in JSON format so I used (http://pastie.org/9364908#16) to get my data into JSON which then comes out like (http://pastie.org/9364674#18)
My question is when I make the template for this, does it need to be all contained in the page that the call to get the json data is? I have looked at examples of mustache templates, but all I can find is it being used with data supplied right then made in JSON format, but my data I need is being supplied when I make the call so how would I go about setting that up.?
When working with mustache js templates (or js templates in general), you do not need to have the template be in the same location as the data being returned from the ajax call. However, you will need to have the data stored in a var that is within scope of the render function of the template. I am assuming you wish to ajax in a set of data, parse it to JSON, then at some point render that JSON data to the DOM. So to answer your questions:
1) Does the template need to be contained in the page that the JSON data is?
Not necessarily, but you will need to be able to access both parts from one locations (ie, you would ajax in both the template and the data, then put it together. Alternatively, you could store the template in the DOM as a script [recommended way unless you are using AMD], and then render the template when your ajax call is complete).
The main thing to note is you will need to have a reference to both your template and your data in the same scope.
2) Setting up the template / data ?
This can be done by using the ajax success callback: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
So on success, you can have the function call render on your template, or just set a locally scoped variable with the data and handle the template rendering after.
3) render the template normally
var template = $('#template').html(), //script tage with id="template" from your dom
data = jsonData, //saved somewhere in a local scoped var .. maybe from an ajax call
rendered = Mustache.render(template, data),
target = $("#target"); //where the template renders to
$('#target').html(rendered);
4) render the template via $.ajax
$.ajax("/api/data", function(data){
var jsonData = $.parseJSON(data),
template = $('#template').html(), //script tage with id="template" from your dom
rendered = Mustache.render(template, jsonData),
target = $("#target"); //where the template renders to
});

Asynchronous jQuery templates

I would like to be able to create jQuery templates that gets filled in by data fetched by some asynch queries, for this I need to refer back to elements I render within a template. I have come up with a solution using a generated class-name, which I use after rendering the template to insert the data, but this is a kludge. Is there a way to get a reference to the rendered element from within the template code? Here is the code I would like to get working:
<script>
function renderData(prduct_id, element){
getProductData(product_id, function(data){
$(e).empty();
$("#product-info-tmpl").tmpl({"data":data}).appendTo($(element));
});
}
</script>
<script id="product-info-loading-tmpl" type="text/x-jquery-tmpl">
loading
//Here is where I'd need a reference to the rendered element
${renderData(product_id, this_element_when_rendered)}
</script>
Does this help, so in your case something with $item, maybe $item.parent or something...
Copied somewhere from http://api.jquery.com/template-tag-equal/
The $item and $data Template Variables
The following variables are exposed to
expression evaluation within
templates:
$: The jQuery object. $item: The
current template item - which allows
access to $item.data, $item.parent,
etc. as well as any user-defined
values or methods passed in with the
options map. $data: The current data
item (equivalent to $item.data). Note:
A template tag with content such as
{{each}}...{{/each}} may expose
additional variables to template
evaluation within the content. In the
case of {{each}}, for example, the
additional template variables $value
and $index are provided within the
content of the {{each}} tag.

Categories