AngularJS with WebAPI, WebAPI Get method getting skipped - javascript

I have two applications, one is a WebAPI application that just serves data. The other is an AngularJS application that gets that data. I'm having a problem with my WebAPI GET method.
I'm trying to use URL parameters to call the correct GET method. From what I understand is that AngularJS will create the URl query for me, and the WebAPI will look for the correct GET method with the correct parameters.
What I'm having trouble with is that my correct GET method is getting skipped by the WebAPI because it doesn't think that the parameters in the URL query match up to the request. It essentially removes/ignores the parameters in the GET method, but I already have a blank GET method. So I'm getting a Multiple actions were found that match the request: error.
This is how my WebAPI looks. Note that the second GET method needs an SearchParameters object which just has two fields. SearchVariable which is what to search for, and SearchTerm which is what field(column) to search for the variable in.
public class ProductsController : ApiController
{
// GET: api/Products
public IEnumerable<Product> Get()
{
var productRepository = new ProductRepository();
return productRepository.Retrieve();
}
// GET: api/Products
public IEnumerable<Product> Get(SearchParameters search)
{
var productRepository = new ProductRepository();
var products = productRepository.Retrieve();
if(search.SearchField == null)
{
return products;
}
IEnumerable<Product> result = null;
// Search on a certain field for the search variable
switch(search.SearchType)
{
case "Product Code":
result = products.Where(p => p.ProductCode.ToUpper().Contains(search.SearchField.ToUpper()));
break;
case "Product Name":
result = products.Where(p => p.ProductName.ToUpper().Contains(search.SearchField.ToUpper()));
break;
}
return result;
}
}
This is my Controller where I'm calling the WebAPI.
(function () {
"use strict";
var app = angular.module("productManagement")
var ProductListCtrl = function($scope, productResource) {
var vm = this;
vm.searchCriteria = {
searchVariable: null,
searchTerm: "Product Name"
};
productResource.query(function (data) {
vm.products = data;
});
$("#searchBtn").click(function () {
productResource.query({ search: vm.searchCriteria }, function (data)
{
vm.products = data;
});
});
$("#searchCategories li").click(function (e) {
e.preventDefault();
var selText = $(this).text();
vm.searchCriteria.searchTerm = selText;
$scope.$apply();
});
}
app.controller("ProductListCtrl", ["$scope", "productResource", ProductListCtrl]);
}());
I set my searchCriteria object from a search box on the UI. This is how the UI looks like.
<div class="panel panel-primary"
ng-controller="ProductListCtrl as vm">
<div class="panel-heading"
style="font-size:large">
<div class="span5" style="display: inline;">
Product List
</div>
<div class="span2 pull-right" style="display: inline;">
<label id="searchTerm" for="searchItem" style="font-size: large; font-weight: normal;">
{{ vm.searchCriteria.searchTerm }}
</label>
<input id="searchItem" type="search" style="color: #337ab7;" ng-model="vm.searchCriteria.searchVariable"/>
<div class="btn-group btn-group-sm" style="vertical-align: top;">
<button id="searchBtn" type="button" class="btn btn-default">Search</button>
<button id="searchCategoryBtn" class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" role="button" >
<i class="caret"></i>
</button>
<ul id="searchCategories" class="dropdown-menu" role="menu">
<li>Product Code</li>
<li>Product Name</li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<td><b>Product</b></td>
<td><b>Code</b></td>
<td><B>Available</b></td>
<td><B>Price</b></td>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in vm.products">
<td>{{ product.productName}}</td>
<td>{{ product.productCode }}</td>
<td>{{ product.releaseDate | date }}</td>
<td>{{ product.price | currency }}</td>
</tr>
</tbody>
</table>
</div>
Why is it that my WebAPI is skipping over my second GET method when the search parameter is clearly getting put on the URL in my Controller? The problem isn't about defining duplicate methods with the same name but different parameters. It's about the WebAPI skipping over the second GET method because it doesn't recognize the search parameter when looking to see if the search parameter in the URL matches with a search parameter in the methods.
The moment I change public IEnumerable<Product> Get(String search) to public IEnumerable<Product> Get(SearchParameters search), the error appears.

Related

Form modal binding in laravel with vue js

I have 2 models Tour.php
public function Itinerary()
{
return $this->hasMany('App\Itinerary', 'tour_id');
}
and Itinerary.php
public function tour()
{
return $this->belongsTo('App\Tour', 'tour_id');
}
tours table:
id|title|content
itineraries table:
id|tour_id|day|itinerary
In tour-edit.blade.php view I have used vue js to create or add and remove input field for day and plan dynamically.
Code in tour-create.blade.php
<div class="row input-margin" id="repeat">
<div class="col-md-12">
<div class="row" v-for="row in rows">
<div class="row">
<div class="col-md-2">
<label >Day:</label>
<input type="text" name="day[]"
class="form-control">
</div>
<div class="col-md-8">
{{ Form::label('itinerary', " Tour itinerary:", ['class' => 'form-label-margin'])}}
{{ Form::textarea('itinerary[]',null, ['class' => 'form-control','id' => 'itinerary']) }}
</div>
<div class="col-md-2">
<button class="btn btn-danger" #click.prevent="deleteOption(row)">
<i class="fa fa-trash"></i></button>
</div>
</div>
</div>
<div class="row">
<button class="btn btn-primary add" #click.prevent="addNewOption" >
<i class="fa fa-plus"></i> Add Field</button>
</div>
</div>
</div>
I want to populate these fields with their respective data. But all data i.e itinerary belonging to a tour are being displayed in itinerary textbox in JSON format.
My vue js sript is:
<script>
var App = new Vue({
el: '#repeat',
data: {
day:1 ,
rows:[
#foreach ($tour->itinerary as $element)
{day: '{{$element->day}}', plan: '{{$element->plan}}'},
#endforeach
]
},
methods: {
addNewOption: function() {
var self = this;
self.rows.push({"day": "","itinerary":""});
},
deleteOption: function(row) {
var self = this;
self.rows.splice(row,1);
},
}
});
</script>
I would avoid mixing blade into JavaScript, instead the best option is to make an ajax call to an api route which returns your data in json, which can then be processed by Vue:
methods:{
getItinerary(){
axios.get('api/itinerary').then(response => {
this.itinerary = response.data;
})
}
}
However, with this approach you will likely need to use vue-router rather than laravel web routes, which puts us into SPA territory.
If that's not an option (i.e. you still want to use blade templates), you should take a look at this answer I gave the other day which shows you how to init data from your blade templates.
What you seem to be doing is using laravel's form model binding to populate your forms, not Vue, so your model data is not bound to the view. So, you will need to decide which one you want to use. If it's vue you just want to use a normal form and bind the underlying data to it using v-model:
Now any updates in the view will automatically be updated by Vue. I've put together a JSFiddle that assumes you will want to continue using Laravel web routes and blade templates to show you one approach to this problem: https://jsfiddle.net/w6qhLtnh/

sharing data between templates in angular, how to?

I have 2 template, in 1st template I use the function and after its successful implementation,i want to get data in a 2nd template. How can I do it? Both template using the same controller
My 1st template:
<form ng-submot='vm.search(q)' class="header-search">
<input class="header-search-input" ng-model='q' placeholder="Search">
<button type="button" class="btn btn-default ic-search" aria-label="Left Align" ng-click='vm.search(q)'>
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
</form>
My 2nd template:
<h3>Результат поиска по запросу: {{q}}</h3>
<ul ng-repeat='item in items'>
<li>{{item.name}}</li>
</ul>
controller:
(function() {
'use strict';
angular
.module('beo.layout.controllers')
.controller('NavbarController', NavbarController);
NavbarController.$inject = ['$scope', '$http', '$location'];
function NavbarController($scope, $http, $location) {
var vm = this;
vm.logout = logout;
vm.search = search;
function search(q) {
$http.post('/api/v1/search/', {
q: q
}).success(function(data) {
$location.path('/search/')
$scope.q = q;
$scope.items = data;
})
}
})();
I would suggest you use cache for best practice. While you are using two templates and when you load your another template it's also going to reload your controller. If you are done with your search in first template then you can save result in cache and then when you redirect to template then just look into that if there is any result then just show it.
Setting $scope equal to the value of the input field should allow you to pass the data from the 1st template to the 2nd template.
Use ng-if to switch between two piece of HTMl snippets. By the way, template is a special term in Angular, indicating something like template in a directive.
For example:
<div ng-if="!items">
<form ng-submot='vm.search(q)' class="header-search">
<input class="header-search-input" ng-model='q' placeholder="Search">
<button type="button" class="btn btn-default ic-search" aria-label="Left Align" ng-click='vm.search(q)'>
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
</form>
</div>
<div ng-if="items">
<h3>Результат поиска по запросу: {{q}}</h3>
<ul ng-repeat='item in items'>
<li>{{item.name}}</li>
</ul>
</div>
After you have retrived the data successfully, i.e., the variable items is true, Angular will switch to the 2nd template for you.
NOTE: you are using vm (this) and $scope on the controller at them same time, which is not encouraged.
To do it "The angular way" you should use directives. Within directives you can require controllers of other directives so you can share data as you need. An example is here: How to require a controller in an angularjs directive
You can get data after a user clicks on the search button, in your code i.e. through vm.search function in the controller which should be used to get data through an api call check this below example.
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
function DefaultController() {
var vm = this;
vm.items = [];
vm.search = search;
function search(searchTerm) {
// perform ajax call and set data here on vm.items property
vm.items = data;
}
}
var data = [
{ name: 'Audi' },
{ name: 'Lamborghini' },
{ name: 'Jaguar' }
];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<form name="searchForm" novalidate="novalidate" ng-submit="searchForm.$valid && ctrl.search(ctrl.searchTerm)">
<label for="searchBox">Search</label>
<input type="text" name="searchBox" ng-model="ctrl.searchTerm" ng-required="true">
<button ng-click="isSubmitted = true">Submit</button>
<span style="color: red;" ng-show="isSubmitted && searchForm.searchBox.$invalid">Search term is required</span>
</form>
<label ng-show="ctrl.items.length">Items matching your search</label>
<div ng-repeat="item in ctrl.items">
{{item.name}}
</div>
</div>
</div>

Generate and track same template multiple times using Knockout in MVC view?

I put together a Contacts prototype MVC application that uses Knockoutjs. I'm fairly new to Knockout and was wondering if my design is correct in reaching my end goal. My end goal is basically to take an MVC Model that is passed to my Contacts view to start and achieve the following:
Mapping it to my KO Viewmodel.
Use Bootstrap Modal Popup to input my contact data.
Upon Clicking Add in Bootstrap Modal call template after posting JSON
data to controller successfully and have it display under
Edit button on each template rendered under div if clicked brings up same Modal Popup to edit that templates data.
Here's the code breakdown of what I have currently in place.
View Code
<h2>Contacts List</h2>
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-10"><h3>KO Results</h3></div>
</div>
<br />
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-10"><div id="koResults" data-bind="template: { name: 'contactSectionTmp', foreach:Contacts }"></div></div>
</div>
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-10"><strong>Add</strong></div>
</div>
#*I enter data in my bootstrap modal shown below and when I click "Add" the Template below appears
in div element koResults with the data I just entered. This is the desired effect I'm looking for. *#
<div class="modal" id="contactModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" style="background-color:#B8E28D; border-color: black">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add Contact</h4>
</div>
<div class="form-horizontal">
<form id="contactModalForm" data-bind="with:newContact,submit:add">
<div class="modal-body">
<h4>Contact</h4>
<div class="form-group">
<label class="col-sm-4 control-label">Name:</label>
<div class="col-sm-8">
<input type="text" name="Name" class="form-control" data-bind="value: Name" />
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Address:</label>
<div class="col-sm-8">
<textarea rows="4" cols="50" name="Address" class="form-control" data-bind="value: Address"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Phone:</label>
<div class="col-sm-8">
<input type="text" name="Phone" class="form-control" data-bind="value: Phone" />
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" id="formSubmitContact" class="btn btn-success">Add</button>
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
#section scripts
<script type="text/javascript" src="~/Scripts/knockout-3.4.0.debug.js"></script>
<script type="text/javascript" src="~/Scripts/knockout.mapping-latest.debug.js"></script>
#* Knockout Template *#
<script id="contactSectionTmp" type="text/html">
<div class="row">
<div class="col-lg-3">Name:</div>
<div class="col-lg-9" data-bind="text: name"></div>
</div>
<div class="row">
<div class="col-lg-3">Address:</div>
<div class="col-lg-9" data-bind="text: address"></div>
</div>
<div class="row">
<div class="col-lg-3">Phone:</div>
<div class="col-lg-9" data-bind="text: phone"></div>
</div>
</script>
End Section
Controller Code
Pass in model to view here.
public ActionResult ContactsList()
{
ContactsVM mData = new ContactsVM();
mData.Contacts = new List<Contact>(){ new Contact { ID = 1, Name="Drew Lucacca", Address="782 Select St.", Phone="421-821-9101"},
new Contact {ID = 2, Name="Kevin Rosassa", Address = "222 Potter Lane", Phone="421-982-5222" },
new Contact {ID = 3, Name="Tim Kropp", Address = "440 PPG Place", Phone="725-434-8989"} };
return View(mData);
}
[HttpPost]
public ActionResult ContactCreate(Contact newContact)
{
var res = newContact;
ContactsVM myContacts = new ContactsVM();
myContacts.Contacts = new List<Contact>();
myContacts.Contacts.Add(new Contact { ID = 4, Name = "Santa Claus", Address = "440 Trump Plaza", Phone = "774-489-8989" });
return Json(myContacts);
}
Javascript Code
` //Main ViewModel
function ContactsVM(data) {
var self = this;
var mapping = {
'Contacts': {
create: function(options) {
return new Contact(options.data);
}
}
};
ko.mapping.fromJS(data, mapping, self);
self.newContact = ko.observable();
self.addContact = function() {
debugger;
self.newContact(new Contact({Name: '', Address: '', Phone: ''}));
}
self.add = function () {
debugger;
var jsData = data;
var jsData1 = ko.mapping.toJSON(self.newContact());
$.ajax({
url: '#Url.Action("ContactCreate", "Home")',
type: 'POST',
data: ko.mapping.toJSON(self.newContact()),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (jsonObject) {
self.contacts.push(new Contact(jsonObject));
}
});
// Close the modal.
$('#contactModal').modal('toggle');
};
self.cancel = function () {
// Close the modal.
$('#contactModal').modal('toggle');
};
//self.resetForm = function (formId) {
// var form = $('#' + formId);
// form.validate().resetForm();
// form.get(0).reset();
//};
};
function Contact(data) {
ko.mapping.fromJS(data, {}, this);
this.isEdit = ko.observable(false);
};
$(function () {
var jsonModel = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model));
var vm = new ContactsVM(jsonModel);
ko.applyBindings(vm);
});
Contact Entity
public class Contact
{
public int ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
ContactsVM Entity
public class ContactsVM
{
public List<Contact> Contacts { get; set; }
}
EDIT #1
See here's the thing I know that the javascript isn't correct and note that in javascript comments asking if you can help me identify if it isn't correct how should it be.
I moved the code to new location at bottom of MVC view for the Javascript code didn't seem to find model.
Javascript - Knockout - Mapping Error
JavaScript runtime error: 'push' is undefined
self.contacts.push(new Contact(jsonObject)); < --- Error happens here.
Any help here would be greatly appreciated and I'm sure would help others as well.
I think it might be best for you to take an iterative approach at getting this working, based on the steps you have listed. Do one thing at a time, get it working, then move on to the next item. Trying to work out everything at once and test it altogether is really tough.
First Recommendation: Make your client-side models reflect your server-side models. After that, things just get easier. Since you are using ko mapping, your client-side model setup gets easier:
function ContactsVM(data) {
var mapping = {
'Contacts': {
create: function(options) {
return new Contact(options.data);
}
}
};
ko.mapping.fromJS(data, mapping, this);
this.newContact = ko.observable();
}
function Contact(data) {
ko.mapping.fromJS(data, {}, this);
this.isEdit = ko.observable(false);
}
Then you can create and apply the top-level view model fairly easily as well:
var vm = new ContactsVM(jsonModel);
ko.applyBindings(vm);
This gives you a top-level viewmodel with a fully filled Contacts observable array property. You can use the newContact property for your modal to add a new contact, just fill it with a new Contact instance.
new Contact({Name:'', Address:'', Phone:''})
When you push this new contact to the array of contacts, the DOM will automatically update to display the new contact, so you won't need to use the "ko.renderTemplate" logic that you specified. I imagine you could also show/hide the modal based on if this observable has a value if you wanted to.
Second recommendation: Try doing things with knockout first, and if you can't then use jQuery. I would not recommend using jQuery to serialize form values. Remember, you have direct access to client-side models, so you are no longer dependent upon the DOM. The ko mapping plugin has a method to unmap back to a regular JS object.

Why isn't meteor injecting the text from my template helpers?

Im trying to dynamically generate a table of two different sets of data. My database isnt empty and the returns have been verified as well. but when i check the rendered page the corresponding html isnt there as if nothing as returned.
template/html:
<template name="room">
<div class="container-fluid">
<h1> Sprint Retrospective</h1>
<hr>
<div class="input-group">
<input type="text" class="form-control thoughts" placeholder="Thoughts..." aria-describedby="basic-addon1">
<span class="input-group-addon">
<input id="wentWell" type="checkbox" aria-label="..."> Went Well
</span>
<span class="input-group-addon">
<input id="wentWrong" type="checkbox" aria-label="..."> Went Wrong
</span>
<span class="input-group-btn">
<button class="btn btn-default" type="button">Submit!</button>
</span>
</div>
<hr>
{{#if haveCards}}
<div class="container-fluid">
<div class="row">
<div class="col-xs-6 col-sm-6">
<div class="row">Went Well</div>
{{#each wentWell}}
{{>card}}
{{/each}}
</div>
<div class="col-xs-6 col-sm-6">
<div class="row">Went Wrong</div>
{{#each wentWrong}}
{{>card}}
{{/each}}
</div>
</div>
</div>
{{/if}}
</div>
</template>
Javascript:
"use strict";
/**
*
**/
var Cards = new Mongo.Collection('cards');
var allCards;
var wentWellCards;
var wentWrongCards;
if(Meteor.isClient){
Tracker.autorun(function(){
allCards = Cards.find({},{sort:{createdAt:-1}});
wentWellCards = Cards.find({category:"Went Well"},{sort:{createdAt:-1}});
wentWrongCards = Cards.find({category:"Went Wrong"},{sort:{createdAt:-1}});
});
Template.room.helpers({
haveCards: function(){
if(allCards != null && allCards != undefined && allCards.length > 0)
return true;
return false;
},
wentWell: function(){
return this.wentWellCards;
},
wentWrong: function(){
return this.wentWrongCards;
}
});
}
Jeremy answer its actually more in point, but..
Lets try to fix that code a little bit.
Lets change the wentWell and wentWrong helpers to look more clean like this.
wentWell: function(){
return Cards.find({category:"Went Well"},{sort:{createdAt:-1}});
},
wentWrong: function(){
return Cards.find({category:"Went Wrong"},{sort:{createdAt:-1}});
}
Also for the haveCards helpers you can do something like
haveCards: function(){
return Cards.find().count() >= 1 //for example or return just findOne()
}
Your helpers should return wentWellCards instead of this.wentWellCards, etc.
Your helpers are not reactive, so, when the data is loaded (which happens after the page is rendered) the helpers are not re-run.
Simply, call the reactive methods (the minimongo queries) in the helper directly. This will get them re-run once the data is available
Also, when you check the count, you need to fetch the collection
Cards = new Mongo.Collection('cards');
if(Meteor.isServer){
Meteor.publish('cards', function() {
return Cards.find({},{sort:{createdAt:-1}});
});
}
if(Meteor.isClient){
Template.room.onCreated(function(){
this.subscribe('cards');
});
Template.room.helpers({
haveCards: function(){
var allCards = Cards.find({},{sort:{createdAt:-1}}).fetch();
return (allCards != null && allCards != undefined && allCards.length > 0);
},
wentWell: function(){
return wentWellCards = Cards.find({category:"Went Well"},{sort:{createdAt:-1}});
},
wentWrong: function(){
return wentWrongCards = Cards.find({category:"Went Wrong"},{sort:{createdAt:-1}});
}
});
}
And you will need to publish the collection from the server and subscribe from the template (unless you are using autopublish)

error with an angularjs filter

Based on this jsfiddle : http://jsfiddle.net/2ZzZB/56/
i add the filter solution for my app : http://www.monde-du-rat.fr/zombieReport/popup.html#/ratousearch (ctrl : http://www.monde-du-rat.fr/zombieReport/resources/js/controllers/RatousearchCtrl.js )
//We already have a limitTo filter built-in to angular,
//let's make a startFrom filter
app.filter('startFrom', function() {
return function(input, start) {
start = +start; //parse to int
return input.slice(start);
}
});
Look console, error is getting at the started :
TypeError: undefined is not a function
at http://www.monde-du-rat.fr/zombieReport/resources/js/baseChrome.js:368:22
at http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:180:297
at B.| (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:169:248)
at B.constant (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:179:161)
at B.| (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:169:253)
at B.constant (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:179:161)
at Object.c (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:101:146)
at m.$digest (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:114:386)
at m.$apply (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:118:12)
at k (http://www.monde-du-rat.fr/zombieReport/resources/libs/angularjs/angular-1.3.0-rc.0/angular.min.js:76:374)
The line is
return input.slice(start);
what's wrong ? i didn't see error in the jsfiddle example
HTML :
<div id="results" ng-show="successLordZR">
<p class="myTitle">{{ 'TRS_CTRL3_TEXT1' | translate }} :</p>
<ul class="list-group">
<li class="list-group-item" ng-repeat="post in posts | startFrom:currentPage*pageSize | limitTo:pageSize">
<div class="myClearfix">
<p style="float: left;"><span ng-class="{'girl' : post.sex == 'F', 'boy' : post.sex == 'M'}">#</span> {{post.prefixe}} {{post.name}} ({{post.idLord}})</p>
<p style="float: right;"><i class="fa fa-link"></i> fiche</p>
</div>
</li>
</ul>
<div id="pagination">
<button type="button" class="btn btn-primary btn-xs" ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1"><i class="fa fa-arrow-circle-o-left"></i> {{ 'TRS_CTRL3_PREV' | translate }} </button>
<span> {{currentPage+1}}/{{numberOfPages()}} </span>
<button type="button" class="btn btn-primary btn-xs" ng-disabled="currentPage >= posts.length/pageSize - 1" ng-click="currentPage=currentPage+1"> {{ 'TRS_CTRL3_NEXT' | translate }} <i class="fa fa-arrow-circle-o-right"></i></button>
</div>
</div>
Data json example from laravel : http://www.monde-du-rat.fr/lordrest/public/posts_jsonforced
EDIT 2 , filter in controller:
// populate scope
$scope.posts = response;
$scope.posts = $filter('startFrom')($scope.currentPage*$scope.pageSize);
filter is here : http://www.monde-du-rat.fr/zombieReport/resources/js/filtersZR.js
Seems the posts model in scope comes from RatousearchCtrl? In that controller the scope.posts was initially set to be an empty object and never updated.
That seems to be the reason why post as in ng-repeat 'post in posts' is undefined, which is the value got passed to the startFrom filter.
Can you re-check how posts are supposed to be loaded?
Input might not exist at that exact moment, just change your code to this:
app.filter('startFrom', function() {
return function(input, start) {
start = +start; //parse to int
return (typeof input == 'string') ? input.slice(start) : "";
}
});

Categories

Resources