thanks for the help on this question: Typeahead result formatting, this is a follow up.
My JSON looks like
[{ name="Long Island", type="2", id="1234"}, { name="New York", type="1", id="5678"}]
In the drop down list I need to be able to seperate type 1 from type 2, so
Type 1 heading
type 1 item
type 1 item*
Type 2 heading
type 2 item
type 2 item
If there are no results for type 1, then don't show the heading. Same for type 2.
Is this possible with typeahead and a templating engine? I'm using Hogan but I'm not fussy.
The "Typeahead" way of doing this is to separate your dataset into 2 datasets, one that will only return "type 1" items and another that will return only "type 2" items. In typeahead, each dataset can have its own header, which will behave exactly the way you want it.
$autocomplete.typeahead([{
name: 'location 1',
remote: {
url: 'http://pathtomysite.com/%QUERY?type=1',
dataType: 'jsonp',
valueKey: 'name'
filter: function (parsedResponse) { return parsedResponse.locations; }
},
template: [
'<p class="repo-name">{{name}}</p>',
'<p class="repo-description">{{id}}</p>'
].join(''),
header: '<b>Type 1</b>'
engine: Hogan
}, {
name: 'location 2',
remote: {
url: 'http://pathtomysite.com/%QUERY??type=2',
dataType: 'jsonp',
valueKey: 'name'
filter: function (parsedResponse) { return parsedResponse.locations; }
},
template: [
'<p class="repo-name">{{name}}</p>',
'<p class="repo-description">{{id}}</p>'
].join(''),
header: '<b>Type 2</b>'
engine: Hogan
}])
Given that you don't have control over the JSON part, you have 2 options:
Option 1
Use 2 datasets, with the same query. In one of them, the filter will only return "type 1" entries, in the other the filter will only return "type 2" answers.
That's twice the calls to the JSON, so twice the load on your server. The client side will not see a delay, though, as the queries are concurrent.
That's a hackish solution, but OTOH it's clean (client-side-wise), and requires very little code.
Option 2
Use only 1 dataset, and so some work in your filter. Basically, return an array with an entry for the "type 1" header, then all the type 1 entries, then an entry for the "type 2" header, then all the type 2 entries.
The array is an array of objects. Each object will also have a class member. In the entries for the "type 1" and "type 2" headers set the class to "header" or something along the lines, and:
1) Have your template include the class.
2) Have your CSS make the class unselectable, unclickable, and styled the way you want it.
I like option #1 better.
Related
I have stucked with an issue using refinement list widget of algolia.
First of all my resulting data structure is like that:
[
{
objectID: 999,
title: 'some title',
categories: [
{
id: 444,
name: 'some name',
},
{...},
]
}
]
I have that type of structure on my page:
<ais-instant-search
:search-client="searchClient"
:initial-ui-state="{
index_Name: { query: searchedValue },
}"
index-name="index_Name"
>
<ais-index index-name="index_Name">
<ais-configure
:filters="facetsFilters"
:facets="['categories.id']"
:hits-per-page.camel="items"
/>
<ais-refinement-list attribute="categories.id" />
<div> ...Some other widgets nested in divs as ais-search-box, ais-sort-by, etc </div>
</ais-index>
</ais-instant-search>
Within ais-configure I have passed to filters a facetsFilters variable which contains string with such content:
"categories.id:1 OR categories.id:5"
and it works ok, I'm getting results within selected categories,
problems starts, when i try to get refinement-list here:
<ais-refinement-list attribute="categories.id" />
I have an empty list despite that on dashboard this attribute is added as an attributesForFacetings and in ais-configure filters parameters with categories.id in it also works well.
Any suggestions is highly appreciated !
Problem was in Dashboard of Algolia.
When we clicked on 'searchable' instead of 'filter only' radiobutton for chosen attributeForFaceting - everything starts working good.
I am still fairly new to angular so I was wondering how to best do something like this:
I have a json file that returns a variety of items of type 'course' and type 'tutorial'. Tutorials are related to courses with a field
data = [
{ title: foo1, type: course, id:1},
{ title: foo2, type: course, id:2},
{ title: foo3, type: course, id:3},
{ title: t1, type: tutorial, id:4, related_course:2},
{ title: t2, type: tutorial, id:5, related_course:2},
{ title: t3, type: tutorial, id:6, related_course:3},
...
In my controller I have functions bound to $scope to allow me to filter by type.
Now in my template
<div ng-repeat="item in data | filter:isCourse">
... display course data
<div ng-repeat="item in data | filter.isTutorial">
... display tutorial data
I would like to find a way to make sure the tutorials displayed match the id of the currently displayed course.
Any suggestions?
Thanks!
- V
You should have then be specific with filters, but do make sure that JSON should be in correct format, as I can see most of the values are not there wrap in "(double quotes)
HTML
<div ng-repeat="course in data | filter: {type: 'course'}">
... display course data
<div ng-repeat="tut in data | filter: { related_course: course.id }">
... display tutorial data
Working Fiddle(Thanks #AWolf)
Need help with Kendo Grid, where in I have dynamic columns on Kendo Grid.
dynamicCols- Object is a object which has list of title and value properties which could be dynamic where it could have any number of objects in the list with title, value pair.
Kendo grid works well if JSON has a flat structure which has all properties at same level and I haven't come across this kind of hierarchial/JSON structure until now.
This grid also needs to support server side sorting and filtering with C# Web API, with Kendo Datasource API for server side sorting and filtering.
Existing kendo column mapping
var cols = [
{ field: 'name', title: 'Name', encoded: false },
{ field: 'id', title: 'Id' },
{ field: 'age', title: 'Age }
]
json = [{
name:'XYZ', id:123, age:45,
dynamicCols: [{title:'Gender',value:'Male'},
{title:'Veteran',value:'Yes'}]
}, {
name:'Jim', id:555, age:24,
dynamicCols: [{title:'Gender',value:'Male'},
{title:'Veteran',value:'No'}]
}, {
name:'Nick', id:557, age:78,
dynamicCols: [{title:'Gender',value:'Female'},
{title:'Veteran',value:'No'}]
}]
**Expected Grid**
Name Id Age Gender Veteran
XYZ 123 45 Male Yes
Jim 555 24 Male No
For Json2
json2 = [
{name:'XYZ', id:123, age:45,
dynamicCols: [{title:'SSN',value:'xx-xx-7891'}]
},
{name:'Jim', id:555, age:24,
dynamicCols: [{title:'SSN',value:'xx-xx-7892'}]
},
{name:'Nick', id:557, age:78,
dynamicCols: [{title:'SSN',value:'xx-xx-7895'}]
}];
**Expected Grid**
Name Id Age Gender SSN
XYZ 123 45 Male xx-xx-7891
Jim 555 24 Male xx-xx-7892
You have two options:
When you are done fetching the data and before creating the new Grid, resolve the JSON object and create flat columns object that the Grid accepts
Your second option is to forget the idea of creating dynamic columns and instead have a template column that dynamically resolves what it needs to display. In such cases you create an external function that you can call from your template. This way you do not end up with complicated and crappy templates. How to invoke external function from a template is covered here.
The easiest solution for me has been to make all columns and then end it by hiding those columns I did not need.
Even hiding around 50 columns did not take any noticable time.
(I had the luxury of knowing all potential columns that could appear)
I am trying to make view from json .When I have array of objects .I am able to make view and validate that view .
If I have this array of object ,in that case I make able to view ,
check plunker
http://plnkr.co/edit/eD4OZ8nqETBACpSMQ7Tm?p=preview
[{
type: "email",
name: "email",
required:true
}, {
type: "text",
name: "name",
required:true
}, {
type: "number",
name: "phonenumber",
required:true
}, {
type: "checkbox",
name: "whant to check"
},
{
type: "url",
name: "server Url"
}];
Now the problem occurred when i have json object .I need to show view from json object .I don't know from where I will start work
I have this json
"displayName": display the name of label which is from of input text
field.
inputValues :represent the type of tmput filled .if it is number then
user fill only number , text then user only fill number ,email then
user fill email , if it switch then it is drop down with given
option.
"required" give if field is required or not ?
Assuming your JSON is coming from a configuration file or a service, you can start by obtaining the JSON as a JSON object:
angular.module('myapp', [])
.controller('MyController', ['$scope', function($scope) {
$scope.outputs = {};
$scope.rawInput = JSON.parse( '{"studentName": "abc", \
"input": {\
"loginUser": {\
"displayDetail": "UserId for login.",\
"displayName": "Login User Id*",\
"inputType": "TEXT",\
(I had to escape returns to allow the pretty printed JSON string to be parsed)
Once you have that, you are nearly there. Now you can just go the level of JSON that you require and construct your inputs array:
$scope.formInputs = $scope.rawInput['input'];
$scope.inputs = [];
angular.forEach($scope.formInputs, function(value, key) {
/* do something for all key: value pairs */
$scope.inputs.push({"type":value.inputType.toLowerCase(),"name":value.name,"required": value.required})
});
Note you should probably do some error checking here - for the purposes of this example, I don't use any. Here is a working plnkr that demonstrates this code.
I haven't got it all to work - you'll have to construct your select or radio button inputs, but I think you should be able to take it from here.
EDIT I have undated the plnkr to make it public
A have an app where the filter for the content changes based on what button is clicked. For more of the straightforward filters, I've been able to figure it out. But now I'd like to create a filter that shows content that has a value within a certain range.
Here is the function I'm trying to use:
$scope.isGood = function(item){
if(!isNan(item.rating)){
return (item.rating>49);
}
return alert("Something broke!!");
//returns true if the item has a high rating (is good, 50+)
//returns false if the item has a poor rating (is bad, 49-)
}
Because the filter changes based on what part of navigation is clicked, and the navigation is dynamic, for the on-click of each navigation button, I run a function that grabs the filter from its link.filter section and places it into $scope.selectedFilter, a variable that is used in my ng-repeat like so:
<tr class="progress" ng-repeat="idea in ideas | filter:selectedFilter">
Since I have a handful of filters, rather than inject my own $filter and require to chain a bunch together, I'd like to write something that will fit in the $scope.selectedFilter variable, since I'd only like one filter on at a time anyways.
Here is an example of the way the dynamic navigation is set-up:
$scope.links = [
{'name':'About', //title that will be displayed on the link
'URL': '#/about', //URL/view that the link will lead to/show
'filter':'' //view may simply change so some info is hidden or revealed
},
{'name':'Active',
'URL': '#/active',
'filter': {active: true} //these {active...} buttons are straightforward and work
},
{'name':'Inactive',
'URL': '#/active',
'filter':{active: false}
},
{'name':'Good Rating',
'URL': '#/active',
'filter': 'isGood(item.rating)' //this is the function I want to filter by when clicked
},
{'name':'Bad Rating',
'URL': '#/active',
'filter':'!isGood(item.rating)'
}
];
Here is my content I want to filter:
$scope.ideas = [
{'title':'Title A',
'rating': 80,
active: true
},
{'title':'Title B',
'rating': 55, //this would have a "good rating"
active: false
},
{'title':'Title C',
'rating': 10, //this would have a "bad rating"
active: true
}
];
But I can't get my filter to work and I'm unsure where I'm going wrong. I'm rather new to Angular, did I botch my syntax somewhere? I was trying to copy the waythis answer was written, but no-luck.
Any help would be appreciated. Thanks!
The problem is that the filter value was defined as a string, it needs to be a real function. This function can then call isGood in turn. So the following should work:
{
'name':'Good Rating',
'URL': '#/active',
'filter': function(item) {
return $scope.isGood(item.rating);
}
}