Angular filtering doesn't work - javascript

In my template I have this code:
<li class="row timeline-item" data-ng-repeat="item in data | filter:workoutFilter" data-ng-include="getTemplateUrl(item)"></li>
And in my controller I have:
$scope.workoutFilter = null;
$rootScope.$on('workout', function(e, data) {
$scope.workoutFilter = "{Type: 'workout'}";
});
When I click button workouts, everything just disappears as if there are no items that match this filter, but that isn't the case (and I know this for a fact because getTemplateUrl detects type workout and returns right template)
Why is this happening ? Is there any other way I can filter items which have property Type "workout" ?
EDIT
Here is what happens when I click button:
In my other controller :
$scope.onWorkoutsClick = function () {
feedService.setWorkoutFilter();
};
In service:
setWorkoutFilter : function() {
$rootScope.$broadcast('workout');
}
And in my main controller:
$rootScope.$on('workout', function(e, data) {
$scope.workoutFilter = "{Type: 'workout'}";
});

I assume you're trying to filter based on item.Type == 'workout'?
You need to set your filter to an object rather than a string:
$scope.workoutFilter = {Type: 'workout'};

Related

AngularJS - Get printed value from scope inside an attribute?

I'm currently working on an AngularJS project and I got stuck in this specific requirement.
We have a service that has all the data, DataFactoryService. Then, I have a controller called DataFactoryController that is making the magic and then plot it in the view.
<div ng-repeat = "list in collection">
{{list.name}}
...
</div>
Now, we have a requirement that pass multiple data into one element. I thought an "ng-repeat" would do, but we need to have it inside an element attribute.
The scenarios are:
At one of the pages, we have multiple lists with multiple data.
Each data has a unique code or ID that should be passed when we do an execution or button click.
There are instances that we're passing multiple data.
Something like this (if we have 3 items in a list or lists, so we're passing the 3 item codes of the list):
<a href = "#" class = "btn btn-primary" data-factory = "code1;code2;code3;">
Submit
</a>
<a href = "#" class = "btn btn-default" data-factory = "code1;code2;code3;">
Cancel
</a>
In the example above, code1,code2,code3 came from the list data. I tried several approach like "ng-repeat", "angular.each", array, "ng-model" but I got no success.
From all I've tried, I knew that "ng-model" is the most possible way to resolve my problem but I didn't know where to start. the code below didn't work though.
<span ng-model = "dataFactorySet.code">{{list.code}}</span>
{{dataFactorySet.code}}
The data is coming from the service, then being called in the controller, and being plot on the HTML page.
// Controller
$scope.list = dataFactoryService.getAllServices();
The data on the list are being loaded upon initialization and hoping to have the data tags initialized as well together with the list data.
The unique code(s) is/are part of the $scope.list.
// Sample JSON structure
[
{ // list level
name: 'My Docs',
debug: false,
contents: [ // list contents level
{
code: 'AHDV3128',
text: 'Directory of documents',
...
},
{
code: 'AHDV3155',
text: 'Directory of pictures',
...
},
],
....
},
{ // list level
name: 'My Features',
debug: false,
contents: [ // list contents level
{
code: 'AHGE5161',
text: 'Directory of documents',
...
},
{
code: 'AHGE1727',
text: 'Directory of pictures',
...
},
],
....
}
]
How can I do this?
PLUNKER -> http://plnkr.co/edit/Hb6bNi7hHbcFa9RtoaMU?p=preview
The solution for this particular problem could be writing 2 functions which will return the baseId and code with respect to the list in loop.
I would suggest to do it like below
Submit
Cancel
//inside your controller write the methods -
$scope.getDataFactory = function(list){
var factory = list.map( (a) => a.code );
factory = factory.join(";");
return factory;
}
$scope.getDataBase= function(list){
var base= list.map( (a) => a.baseId);
base= base.join(";");
return base;
}
Let me know if you see any issue in doing this. This will definitely solve your problem.
You don't really have to pass multiple data from UI if you are using Angular.
Two-way data binding is like blessing which is provided by Angular.
check your updated plunker here [http://plnkr.co/edit/mTzAIiMmiVzQfSkHGgoU?p=preview]1
What I have done here :
I assumed that there must be some unique id (I added Id in the list) in the list.
Pass that Id on click (ng-click) of Submit button.
You already have list in your controller and got the Id which item has been clicked, so you can easily fetch all the data of that Id from the list.
Hope this will help you... cheers.
So basing from Ashvin777's post. I came up with this solution in the Controller.
$scope.getFactoryData = function(list) {
var listData = list.contents;
listData = listData.map(function(i,j) {
return i.code;
});
return listData.join(';');
}

how to toggle particular div element in ng-repeat?

I have list of product , If I click on one product it needs to be added in database and again if I click on same product it should be removed from database, I am toggling wishlistFlag on ng-click. It should be fine on one div element, for second div element it is working reverse of first div element, I mean in case first product is added then if I click second product it has to be added but it is removing first product.
<div class="hmpal-prprt-post-wdgt hmpal-prprt-wishlist">
<a href="">
<span class="prprt-icon"><i class="fa fa-heart" aria-hidden="true"
ng-click="WishlistAdd($index,project.propertyId)"></i></span>
<span>Wishlist</span>
</a>
</div>
And inside Controller code is here,
a.WishlistAdd = function (index,propertyId) {
a.wishlistFlag = !a.wishlistFlag;
var data = {
wishlistFlag:a.wishlistFlag,
propertyId:propertyId
};
e.createWishLists(data).then(function (result) {
alert("sucesss");
alert(JSON.stringify(result));
}, function (error) {
alert("error");
alert(JSON.stringify(error));
});
}
How I can implement toggle wishlistFlag for different product .
Since you want at most one product selected in your wish list, instead of having a boolean flag, you can use the selected product id (called propertyId in your code if I'm right). The selectedProductId variable, defined in the controller, is either null if there is no product selected, or the product id if there is one.
The toggling is done by checking if the current selected id is equal to the clicked one.
I assume that
when wishListFlag === true in the sent data, you want to add the
product identified by propertyId, and otherwise, remove the
product from the database.
when you add a product, the server side
actually replace the selected product if there is an existing one.
// Is there a selected product ?
var selectedProductId = null;
a.WishlistAdd = function (index, propertyId) {
selectedProductId = (selectedProductId === propertyId ? null : propertyId);
var data = {
wishlistFlag: (selectedProductId !== null),
propertyId: propertyId
};
e.createWishLists(data).then(function (result) {
alert("sucesss");
alert(JSON.stringify(result));
}, function (error) {
alert("error");
alert(JSON.stringify(error));
});
}
You can make use of $index to have seperate flag to each of the wishList. Here, you can write your code as..
a.wishListFlag[index]
maintain a array of added propertyIds before save to the database check that id is in array if so remove from database and array else remove from database and array.
var wishList = [];
a.WishlistAdd = function (index,propertyId) {
var data = {
wishlistFlag: wishList.indexOf(propertyId) === -1,
propertyId:propertyId
};
e.createWishLists(data).then(function (result) {
//add or remove propertyid from whishList
if(data.wishlistFlag)
wishList.push(propertyId);
else
wishList.splice(wishList.indexOf(propertyId), 1);
alert("sucesss");
alert(JSON.stringify(result));
}, function (error) {
alert("error");
alert(JSON.stringify(error));
});
}

Angular - mdDataTable pagination is not working properly

I'm using an angular library that's called mdDataTable to handle my tables with searching, paging and so on.
I am trying to reproduce the functionality from the "Ajax Search Support" demo on this demo page, but I can't get it to work. Searching works fine, but my paging will only show that one page is avalible even if the results is eleven items and my pageSize is set to 5 per page.
I'm not sure how to simulate an api-call on codepen so I'll paste the code.
I also depend on Angular material and $resource. $resource is my "dataService" and then I have a service called paginationHandler, that's really just picks up pagination information in the response headers from the server (Custom header) and stores it for the application to use. I got an interceptor that handles storing that data.
My view containing the table:
<md-card class="bg-white" layout-fill md-whiteframe="4db">
<md-input-container class="padder-md m-t-xl">
<label style="padding-left: 20px; padding-right: 20px;">Sök användare</label>
<input type="text" ng-model="filterText">
</md-input-container>
<mdt-table paginated-rows="{isEnabled: true, rowsPerPageValues: [5,10,20,50,100]}"
mdt-row-paginator="vm.paginatorCallback(page, pageSize)"
sortable-columns="true"
animate-sort-icon="true"
mdt-row-paginator-no-results-message="Inga resultat hittades..."
mdt-row-paginator-error-message="Fel uppstod vid hämtning av maskinmodeller."
mdt-trigger-request="vm.getLoadResultsCallback(loadPageCallback)"
mdt-row="{
'table-row-id-key': 'id',
'column-keys': [
'name',
'category',
'machineModelType.name',
'createdDate',
'remove'
],
}">
<mdt-header-row>
<mdt-column align-rule="left">Namn</mdt-column>
<mdt-column align-rule="left">Kategori</mdt-column>
<mdt-column align-rule="left">Typ</mdt-column>
<mdt-column align-rule="left">Skapad</mdt-column>
<mdt-column align-rule="left">Ta bort</mdt-column>
</mdt-header-row>
</mdt-table>
</md-card>
And this is my controller. It's a route in ui-router that has the controller defined in that route "as vm", so I haven't forgotten to link the controller to the view.
(function () {
"use strict";
angular.module("app")
.controller("detailsManufacturerCtrl", [
"$stateParams",
"dataService",
"$scope",
"paginationHandler",
function ($stateParams, dataService, $scope, paginationHandler) {
var vm = this;
vm.machineModels = [];
// Data retrieval
vm.getMachineModels = function(){
dataService.manufacturerMachineModels.query({manufacturerId: $stateParams.id, sort: "name", page: 1, pageSize: 5, search: ""}, function(response){
vm.machineModels = response;
vm.pagination = paginationHandler.get();
});
};
// Machine Model Table Functions
vm.paginatorCallback = function(page, pageSize){
var query = $scope.filterText ? $scope.filterText : '';
return uow.manufacturerMachineModels.query({
manufacturerId: $stateParams.id,
sort: "name",
page: page,
pageSize: pageSize,
search: query
}).$promise.then(function(result){
return {
results: result,
totalResultCount: result.length
}
});
};
var loadPageCallbackWithDebounce;
$scope.$watch('filterText', function(){
if(loadPageCallbackWithDebounce){
loadPageCallbackWithDebounce();
}
});
vm.getLoadResultsCallback = function(loadPageCallback){
loadPageCallbackWithDebounce = _.debounce(loadPageCallback, 500);
};
// INIT
vm.getMachineModels();
}
])
}());
It's close to the demo except for the item properties and the dataservice is my own ofc.
This is where my ajax-call ends up. I use ASP.NET Web Api 2 as server.
[Route("", Name = "ManufacturerMachineModelList")]
public async Task<IHttpActionResult> Get(int manufacturerId, // Url values
// Filtering (None)
string sort = "name", // Sorting
int page = 1, int pageSize = 5, //Pagination
string search = "") // Search
{
try
{
var manufacturer = Uow.Manufacturer.GetById(manufacturerId);
// Not Found
if (manufacturer == null) { return NotFound(); }
var machineModels = Uow.MachineModel.GetAll(sort, search)
// Url filter
.Where(mm => mm.ManufacturerId == manufacturerId)
// Query filters (None)
.ToList();
// Pagination
var paginationHeader = GetPaginationHeader(machineModels, pageSize, page, sort);
HttpContext.Current.Response.Headers.Add("Pagination", JsonConvert.SerializeObject(paginationHeader));
// Return list and add pagination
return Ok(machineModels
.Skip(pageSize * (page - 1))
.Take(pageSize)
.ToList());
}
catch (Exception exc)
{
return InternalServerError(exc);
}
}
The "GetPaginationHeader()" method returns a anonymous object that looks like this:
var object = new
{
currentPage = page,
pageSize = pageSize,
totalCount = totalCount,
totalPages = totalPages,
previousPageLink = prevLink,
nextPageLink = nextLink
}
Which I then add as a header that's exposed through CORS.
These values are always correct.
The thing is that I'm not really sure what to do with these values, if anything. At the moment I just store the values when the response that includes "Pagination" header comes back and nothing more.
When I make this call I get 11 results back, and the table shows the correct pageSize (5), but not the correct amount of pages (always 1, should be 3), so I only see the first five results.
So, finally, my question is, which values in the ajax search demo should I change to my own values? If none, what else am I doing wrong?
I'm totally stuck so any help is appriciated!
EDIT: I've been trying to get the demo working locally but without luck. If someone can help me get that to work, then I can debug the example and see where I go wrong.

Kendo template send data

What I want is simple but I don't know if it's possible.
I have a Kendo Mobile ListView as below:
e.view.element.find("#list-serviceorders").kendoMobileListView({
dataSource: ds,
pullToRefresh: true,
template: $("#list-serviceorders-template").html()
});
And I want to send to the template some values to access on it. My view with the template is this:
<div data-role="view" data-before-show="GAPCP.viewBeforeShow" id="serviceorders" data-layout="main-item-list">
<ul id="list-serviceorders"></ul>
</div>
<script id="list-serviceorders-template" type="text/x-kendo-template" data-teste="teste">
<a href="views/entries.html?id=#: CodOs #">OS: #: CodOs #<br />
#: parameter.Divi1 #: #: CodDivi1 #/#: parameter.Divi2 #: #: CodDivi2 #</a>
</script>
Where you can read parameter.Divi1 and parameter.Divi2 are the places where I want to display those values. They're are not in the Data Source like the others values.
I don't want to create global variable 'cause I don't want to mess with my code and I can't use a function for that purpose because those values come from the database and it will execute a query for each list item iteration.
Any suggestion of how do that?
What I'm proposing is adding this information to the model in the controller. You can do it in DataSource.schema.parse or in requestEnd, even in a dataBound event if the widget accepts it.
When the data is received you iterate through the model and fills the remaining data not received from the server.
Example: Using parse
var ds = new kendo.data.DataSource({
transport: {
read: {
url : ...
}
},
schema : {
model: {
CodOs : { type: "number" },
CodDivi1: { type: "string" },
CodDivi2: { type: "string" }
},
parse: function (data) {
$.each(data, function (idx, elem) {
// Extend original elem
elem.parameter = {
Divi1: elem.CodDivi1.toUpperCase(),
Divi2: elem.CodDivi2.toLowerCase()
}
});
return data;
}
}
});
Where I compute parameter inside the parse function and set parameter.Divi1 to CodDivi1 in upper-case and parameter.Divi2 to CodDivi2 in lowercase.

Trying to get Jquery working with dynamic select forms in Rails and Active Admin

I'm trying to update a select box based on another..
In my active admin resource, I did the following just for some test data:
controller do
def getcols
list = new Hash
list = {"OPTION1" => "OPTION1", "OPTION2" => "OPTION2"}
list.to_json
end
end
In active_admin.js I have the following
$('#worksheet_type').change(function() {
$.post("/admin/getmanifestcols/", { ws_type: $(this).val() }, function(data) {
populateDropdown($("#column_0"), data);
});
});
function populateDropdown(select, data) {
 select.html('');
alert('hi');
$.each(data, function(id, option) {
select.append($('<option></option>').val(option.value).html(option.name));
});      
}
The above is working in the sense that when my primary select box is changed, the jquery is called and I even get the alert box of 'hi' to be called. However, it's not replacing the contents of the select box with my test OPTION1 and OPTION2 data.
I think I'm passing in the JSON wrong or something, or it's not being read.
What am i missing?
It looks to me as if you're not properly iterating over the map.
What about:
$.each(data, function(value, name) {
select.append($('<option></option>').val(value).html(name));
});
?

Categories