Handlebars variable inside each loop (Accessing object key value) - handlebars.js

One of my components needs to fetch different data from a property based on a parameter I pass it. The parameterHolder is an Object with keys and parameter is the key name.
{{component-name parameterHolderBinding=parameterHolder parameterValueBinding=parameter}}
I'm trying to loop through it like so
{{#each item in parameterHolder.[{{parameter}}]}}
{{/#each}}
But it's not working. When I try,
{{parameterHolder.keyName}}
I'm getting [Object] which is correct. Could someone please point out the right way do this?

I've managed to get it working by dynamically creating new properties.
In my controller -
parameterUpdatedObserver: function ()
{
var reference = this;
$.each(parameterHolder, function (key, value) {
reference.set('parameterHolderName'+key, value);
});
}.observes('parameterHolder')
And my component -
{{component-name parameterHolderBinding=parameterHolderNameKey parameterValueBinding=parameter}}
I can probably abstract it up one more level using another component. If anyone has a better solution, please do post it.

Related

Typescript reflection - required parameters & default values

In short: is there a way to know if a typescript parameter is required and/or has a default value?
Longer version:
Say I have the following file:
//Foo.ts
class Bar {
foo(required:string,defaultValue:number=0,optional?:boolean) {
...
}
}
I would like to know of each of the parameters:
the name
the type
is it required?
does it have a default value?
I have succesfully used method decorators with the TypeScript reflection API to get the types of the parameters, I've used this method to get their names, but so far I have not found a way to know if a variable is required and/or has a default value.
I know the typescript compiler itself can be used from within typescript. So I'm wondering if there is a way to use the parse tree of the compiler to see if a parameter is required and/or has a default value?
How would that work?
If you want to do this from scratch...
On a high level, one way of doing it is to:
Figure out how to get the SourceFile node using the compiler api of your file. That requires a bit of an explanation in itself.
From there, use the api's forEachChild function to loop over all the nodes in the file and find the node with a kind of SyntaxKind.ClassDeclaration and .name property with text Bar.
Then loop over all the children of the class by again using the api's forEachChild function and get the ones that has the kind SyntaxKind.MethodDeclaration and .name property with text foo.
To get the parameters, you will need to loop over the method node's parameters property.
Then for each parameter node, to get the name you can call .getText() on the .name property.
You can tell if the parameter is optional by doing:
const parameterDeclaration = parameterNode as ts.ParameterDeclaration;
const isOptional = parameterDeclaration.questionToken != null || parameterDeclaration.initializer != null || parameterDeclaration.dotDotDotToken != null;
Or you could use the TypeChecker's isOptionalParameter method.
To get its default expression, you will just have to check the initializer property:
propertyDeclaration.initializer;
To get the type use the TypeChecker's getTypeOfSymbolAtLocation method and pass in the symbol of the node... that gets a little bit complicated so I won't bother explaining it (think about how it's different with union types and such).
Don't do it from scratch...
I've created a wrapper around the TypeScript compiler api. Just use this code with ts-simple-ast (edit: Previously this talked about my old ts-type-info library, but ts-simple-ast is much better):
import { Project } from "ts-morph";
// read more about setup here:
// https://ts-morph.com/setup/adding-source-files
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const sourceFile = project.getSourceFileOrThrow("src/Foo.ts");
const method = sourceFile.getClassOrThrow("Bar").getInstanceMethodOrThrow("foo");
Once you have the method, it's very straightforward to get all the information you need from its parameters:
console.log(method.getName()); // foo
for (const param of method.getParameters()) {
console.log(param.getName());
console.log(param.getType().getText());
console.log(param.isOptional());
console.log(param.getInitializer() != null);
}

Best and proper way to use Entity Framework in _Layout

I have a standard ASP.Net template, which has a _Layout where my menu is generated. I have multiple data contexts representing different databases throughout my application and all works fine.
I want to add a count as a bootstrap badge next to one of the items in the _Layout. To do this I need to pass in db.TicketDal.Count(). What is the best way to do this directly into the layout. I did try passing the data in a ViewBag entry from the home controller but then when I go to different controllers that doesn't display. I could modify each controller but that seems the wrong way to do it. I suspect I am overthinking this but any advice would be appreciated.
You must create a BaseController. There you can get the var TicketCount = db.TicketDal.Count(); or some List<MenuItems> let's say and any other controllers must inherit from BaseController so in any of them and in any of their methods you would have the same instance of List<MenuItems> or TicketCount
Or you can create a helper class.
public static class BaseKnowledgeHelper
{
public static int GetTicketCount()
{
return db.TicketDal.Count();
}
}
And call that everywhere: #BaseKnowledgeHelper.GetTicketCount()
I am going to suggest what i suggested on a similar post like this.
I would not create a BaseController, this would load and query the DB every single time (which could be ok) and the UI thread is dependent on the DB call.
What I would do is implement an Ajax call to get this information and then put it on your _Layout
Acton Method
public ActionResult GetTicketCount()
{
//Code to fetch the data for the count
return Json(count, JsonRequestBehavior.AllowGet);
}
Ajax on the View
$(function () {
$.ajax({
type: "GET",
url: '#Url.Action("GetTicketCount","WhatEverController")',
success: function (data) {
// You can now do something with the data which contains the count
// e.g. Find the div where the count is suppose to be and insert it.
}
});
});
This way you are not having to wait for any DB calls to finish, the downside is that the count will not appear at the exact same time as your DOM loads. But you could always make it more friendly looking by using something like Spin.js

Firebase binding in AngularJs

I am having issues binding to an object in firebase. I am using AngularFire and the code in my Angular controller looks like this:
var firebaseCourse = new Firebase("https://torid-fire-1683.firebaseio.com/course-header/course-1");
$scope.course = $firebase(firebaseCourse);
This does successfully connect to firebase and return my data. However, when the object is returned, it is embedded in another object like this:
{"-JDlZpk38i9YsSRoH0ce":{"description":"Course Description","name":"Course One"}}
Thus, when I bind to {{course.name}} in my view, it doesn't work, because the properties are embedded inside another object in the object that $scope.course is bound to.
How do I get around this?
What you are seeing is exactly what firebase sends back. So your code is actually working. I believe that all you have to add is :
$scope.course = $firebase(firebaseCourse).$asArray();
If $asArray() still doesn't give you what you want, you can iterate over the object and create and array. So in your view you can do this:
In your view(html) - instead of - {{courses}} ----> {{getCourses(courses)}}
& in you controller
$scope.getCourses = function(courses) {
var array = [];
for(var key in courses) {
array.push(courses[key]);
}
return array;
}
This way you will have an array or courses instead of a nested object. This will not effect the 3 way binding that is provided by angularFire
Hope this helps! Thanks

copy a Collection element by value in C#

In the code below, a reference type is being added. How can i do this value type?
imgList.Items.Add(imgList.Items[0]);
imgList.Items[imgIndex].Data = input; <== **This updates the 0th and the newly added element which is the issues**
Please advise
In order to avoid this issue, you need to clone imgList.Items[0] before adding it to imgList.Items. This basically involves creating a new object of the same type and populating it with data from the original.
The complexity of doing so depends on what the object is, but look at the answers to this question for some tips on cloning objects.
Edit: I forgot that .MemberwiseClone was protected.
You don't say in your code what the type of object is that you're adding to the list. If it's a class of yours, you can add a method to return a copy:
public MyType ShallowCopy()
{
return (MyType)this.MemberwiseClone();
}
and use
imgList.Items.Add(imgList.Items[0].ShallowCopy());
Or you can add a copy constructor:
public MyType(MyType original)
{
// Copy each of the properties from original
this.Data = original.Data;
}
and use
imgList.Items.Add(new MyType(imgList.Items[0]));

flex 3 and using name/value pairs

Does anyone have any recommendations for working with name/value pairs in Flex?
Context:
I want to create a Flex UI for updating a database table. I want the UI to contain the field name(read only) and current field value (which will be editable). Im using the WebService component to retrieve the field value and then asssigning it to an object with the field name hardcoded e.g.
private function resultHandler(event:ResultEvent):Object
{
var resultsObj:Object;
resultsObj = {
name:event.result.name as String,
This approach however is adding the dependency that the table structure/field names will never change. Using the object type also requries that i write my own algorithm to sort the output.
I'm not sure I understand the issue.
If you want to avoid dependency of the properties returned from the event at this point, simply use the event.result object, which is already an associative array.
As for sorting, we would need more context on what you are attempting to sort.
That's pretty simple. Don't use for each in loop. Use For-In Loop
Demo is shown below.
var dicEntry:Object = new Object();
dicEntry["Name"] = "Raj";
dicEntry["sal"] = 10000;
dicEntry["age"] = 33;
for(var key:Object in dicEntry)
{
trace("Object Key: "+key+" Object Value: +dicEntry[key]);
}
That's it.

Resources