I am using Phreeze to create an application.
Everything goes right but when I want to filter in a template a custom field (tagtypeName) it doesn't do it.
I have the model in model.js:
model.TagModel = Backbone.Model.extend({
urlRoot: 'api/tag',
idAttribute: 'id',
id: '',
name: '',
type: '',
TagtypeName: '',
baja: '',
defaults: {
'id': null,
'name': '',
'type': '',
'baja': ''
}
});
My criteria is TagCriteria.php:
public function GetFieldFromProp($propname)
{
switch($propname)
{
case 'TagtypeName':
return 'tagtype.id';
case 'Id':
return 'tag.id';
case 'Name':
return 'tag.name';
case 'Type':
return 'tag.type';
case 'Baja':
return 'tag.baja';
default:
return parent::GetFieldFromProp($propname);
//throw new Exception('Unable to locate the database column for the property: ' . $propname);
}
}
My reporter is:
public $Id;
public $Name;
public $Type;
public $Baja;
public $TagtypeName;
/*
* GetCustomQuery returns a fully formed SQL statement. The result columns
* must match with the properties of this reporter object.
*
* #see Reporter::GetCustomQuery
* #param Criteria $criteria
* #return string SQL statement
*/
static function GetCustomQuery($criteria)
{
$sql = "select
`tagtype`.`name` as TagtypeName
,`tag`.`id` as Id
,`tag`.`name` as Name
,`tag`.`type` as Type
,`tag`.`baja` as Baja
from `tag`
inner join `tagtype` on `tagtype`.`id`=`tag`.`type`";
// the criteria can be used or you can write your own custom logic.
// be sure to escape any user input with $criteria->Escape()
$sql .= $criteria->GetWhere();
$sql .= $criteria->GetOrder();
return $sql;
}
the view has:
<script type="text/template" id="tagCollectionTemplate">
<table class="collection table table-bordered table-hover">
<thead>
<tr>
<th id="header_Id">Id<% if (page.orderBy == 'Id') { %> <i class='icon-arrow-<%= page.orderDesc ? 'up' : 'down' %>' /><% } %></th>
<th id="header_Name">Name<% if (page.orderBy == 'Name') { %> <i class='icon-arrow-<%= page.orderDesc ? 'up' : 'down' %>' /><% } %></th>
<!--<th id="header_Type">Type<% if (page.orderBy == 'Type') { %> <i class='icon-arrow-<%= page.orderDesc ? 'up' : 'down' %>' /><% } %></th>-->
<th id="header_Type">Type<% if (page.orderBy == 'TagtypeName') { %> <i class='icon-arrow-<%= page.orderDesc ? 'up' : 'down' %>' /><% } %></th>
<th id="header_Baja">Baja<% if (page.orderBy == 'Baja') { %> <i class='icon-arrow-<%= page.orderDesc ? 'up' : 'down' %>' /><% } %></th>
</tr>
</thead>
<tbody>
<% items.each(function(item) { %>
<tr id="<%= _.escape(item.get('id')) %>">
<td><%= _.escape(item.get('id') || '') %></td>
<td><%= _.escape(item.get('name') || '') %></td>
<!--<td><%= _.escape(item.get('type') || '') %></td>-->
<td><%= _.escape(item.get('tagtypeName') || '') %></td>
<td><%= _.escape(item.get('baja') || '') %></td>
</tr>
<% }); %>
</tbody>
</table>
<%= view.getPaginationHtml(page) %>
</script>
and in my controller I've changed the Tag to my reporter:
$tags = $this->Phreezer->Query('TagReporter',$criteria)->GetDataPage($page, $pagesize);
So when I go to the page I see the table instead of with the type id, it has the name of the type from my custome query as needed
but when I filter, no data is found with the new custom field:
Does anyone know how to handle this problem?
The problem was that I had to change the reporter count and put the inner joins:
static function GetCustomCountQuery($criteria)
{
$sql = "select count(1) as counter from `tag`
inner join `tagtype` on `tagtype`.`id`=`tag`.`type`";
// the criteria can be used or you can write your own custom logic.
// be sure to escape any user input with $criteria->Escape()
$sql .= $criteria->GetWhere();
return $sql;
}
Doing this it works OK for me!
Related
I have a page in my React App that renders some locally stored JSON Data into a table. I've been trying for a long time to implement a search bar that will filter through the PostCode column in the table and return the row. So far I've been able to make a search bar that does what I want it to but I haven't been able to integrate it into the page with the table.
My apologies if this is an easy question or I'm way off the mark. I'm a coding novice but have to use React for a project and struggle to get to grips with it.
The code for my table looks like this:
import SearchBar from './SearchBar'
import React,{useState,useEffect} from 'react';
import './App.css';
import { Data } from './NewData.js'
export const JsonReader = () => {
return (
<>
<ArchiveHeader />
<div className="data-container">Welcome to RF</div>
{Data.map((data, key) => {
return (
<div key={key}>
<JsonTable
key = {key}
Username = {data.Username}
Address = {data.Address}
PostCode = {data.PostCode}
Details ={data.Details}
Date ={data.Date}
Score ={data.Score}
/>
</div>
);
})}
</>
);
};
const ArchiveHeader = () => {
return (
<header className="ArchiveHeader">
<h2>Rent Flag</h2>
</header>
);
};
const JsonTable= ({ Username, Address, PostCode, Details, Date, Score }) => {
if (!Username) return <div />;
return (
<table data={Data}>
<tbody>
<tr>
<td>
<h5>{Username}</h5>
</td>
<td>
<h5>{Address}</h5>
</td>
<td>
<h4>{PostCode}</h4>
</td>
<td>
<p>{Details}</p>
</td>
<td>
<p>{Date}</p>
</td>
<td>
<p>{Score}</p>
</td>
</tr>
</tbody>
</table>
);
};
export default JsonReader;
and the code for my searchbar looks like this:
import Papa from "papaparse";
import React, { useState, useEffect } from 'react';
import { Data } from './NewData.js'
import JsonReader from './JsonReader'
export default function SearchBar () {
const [searchTerm,setSearchTerm] = useState('')
return (
<div className="SearchBar">
<input type="text" placeholder="search..." onChange={e=>setSearchTerm(e.target.value)} />
{Data.filter((val)=>{
if(searchTerm == ""){
return val
}
else if(val.PostCode.toLowerCase().includes(searchTerm.toLowerCase())){
return val;
}
}).map((val,key)=>{
return <div>{val.PostCode} </div>
})}
</div>
);
}
You can use useMemo hook for this functionality.
const searchResults = useMemo(() => {
if (!searchTerm) {
return items;
}
return Data?.filter((item) =>
item?.toLowerCase()?.includes(searchTerm?.toLowerCase().trim())
);
}, [Data, searchTerm]);
You can use searchResults variable and render that in your table.
In the same JsonReader function you should:
Create the useState constants [searchTerm, setSearchTerm].
Set a new FData array with filtered data and that is the one you should do the mapping to.
Place the input field on the same page.
And, instead of using the Data.map you will use the FData.map.
This is how your JsonReader function should look like (and the SearchBar function could be discarded):
export const JsonReader = () => {
const [searchTerm, setSearchTerm] = useState("");
const FData = Data.filter((val) => {
if (searchTerm == "") {
return val;
} else if (val.PostCode.toLowerCase().includes(searchTerm.toLowerCase())) {
return val;
}
});
return (
<>
<ArchiveHeader />
<div className="data-container">Welcome to RF</div>
<input type="text" placeholder="search..." onChange={(e) => setSearchTerm(e.target.value)} />
{FData.map((data, key) => {
return (
<div key={key}>
<JsonTable
key = {key}
Username = {data.Username}
Address = {data.Address}
PostCode = {data.PostCode}
Details ={data.Details}
Date ={data.Date}
Score ={data.Score}
/>
</div>
);
})}
</>
);
};
I have two classes:
Row (Child Class)
mySpreadsheet (Parent Class)
I am trying to do something like this:
Row:
class Row extends React.Component {
constructor(props, ref) {
super(props);
this.state = { selectedFile: null}
this.handleUpload = this.handleUpload.bind(this);
}
//This handleUpload is being called by the parent class of this Row class through ref.
handleUpload(ev) {
ev.preventDefault();
const data = new FormData();
data.append('file', this.uploadInput.files[0]);
data.append('filename', this.fileName.value);
data.append('comment',this.comment.value);
data.append('id', this.fileName.id);
fetch('http://localhost:8000/upload', {
method: 'POST',
body: data,
}).then((response) => {
response.json().then((body) => {
this.setState({ selectedFile: `http://localhost:8000/${body.file}` });
});
});
}
rowCreator() {
let row = []
for (var i = 0; i < 10; i++) {
row.push(
<td>
<div>
<input type="file" name={`file${this.props.id*10 + i}`} id={this.props.id*10 + 1} ref={(ref) => { this.uploadInput = ref; }}/>
<input type="text" name={`fileName ${this.props.id*10 + i}`} ref={(ref) => { this.fileName = ref; }} placeholder="Name the file with extension"/>
<input type="text" ref={(ref) => { this.comment = ref; }} placeholder="Comment"/>
</div>
</td>
)
}
return row
}
render() {
return (
<tr>
<td class="align-middle ">
<div class="cell">
<input type="text" placeholder={this.props.id + 1} />
</div>
</td>
{this.rowCreator()}
</tr>
)
}
}
and in mySpreadsheet I am creating each row in a table using Row class as follows:
<tbody id="tbody">
{this.state.data.map(id => (
<Row id={id} ref={this.rowRef} />
))}
</tbody>
I am using the handleUpload() function from the Row (child) by using rowRef:
this.rowRef = React.createRef();
upload(ev) {
this.rowRef.current.handleUpload(ev);
}
<button onClick={this.upload}>
Upload Files
</button>
But I am getting error (500) while doing a POST request through my website. Is it because of the ref I am using in Row such as uploadInput, for appending data in handleUpload? Is there any way to make a unique ref for all the cells in my table? Or can I use something else like id or name which I have made uniquely for all different cells using this.props.id*10 + i for each iteration, i while making columns for one row?
You can create refs for mapped elements and put it in an array based on their indexes or ids.
// constructor state part
constructor() {
this.refs = [];
}
// render part
{this.state.data.map(id => (
return <Row id={id} ref={itemRef => this.refs[id] = itemRef} />
))}
And in my opinion, you should hold the values instead of the components itself in an array.
Id must be unique and if the map parameter is an object, you should use a unique property instead of the key which comes with map. If you use keys, React will not keep track of your component while you' re updating your state.
Using the below SPFx PnP.js code I am doing the CRUD operation in SharePoint online list:
private _getListData(): Promise<ISPList[]> {
return pnp.sp.web.lists.getByTitle("EmployeeList").items.get().then((response) => {
return response;
});
}
private getListData(): void {
this._getListData()
.then((response) => {
this._renderList(response);
});
}
AddItem()
{
pnp.sp.web.lists.getByTitle('EmployeeList').items.add({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
});
alert("Record with Employee Name : "+ document.getElementById('EmployeeName')["value"] + " Added !");
}
UpdateItem()
{
var id = document.getElementById('EmployeeId')["value"];
pnp.sp.web.lists.getByTitle("EmployeeList").items.getById(id).update({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
});
alert("Record with Employee Name : "+ document.getElementById('EmployeeName')["value"] + " Updated !");
}
DeleteItem()
{
pnp.sp.web.lists.getByTitle("EmployeeList").items.getById(document.getElementById('EmployeeId')["value"]).delete();
alert("Record with Employee ID : "+ document.getElementById('EmployeeId')["value"] + " Deleted !");
}
In the above code AddItem() and UpdateItem() are not working but reading list items and deleting list item are working. I mean I am not able to add new record to the list and update also not getting any errors, getting the successful alert message but it is not adding or updating the items. Any issue with the AddItem() and updateItem() function code....any help will be much appreciated.
Updated
I am not getting any error though it add and update function is not working, by the way I am global administrator.
While clicking on the add button getting the successful alert message but it is not adding, screenshot attached:
Complete code reference:
import pnp from 'sp-pnp-js';
//import { default as pnp, ItemAddResult } from "sp-pnp-js";
import { Version } from '#microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '#microsoft/sp-webpart-base';
import { escape } from '#microsoft/sp-lodash-subset';
import styles from './PnPspCrud.module.scss';
import * as strings from 'pnPspCrudStrings';
import { IPnPspCrudWebPartProps } from './IPnPspCrudWebPartProps';
export interface ISPList {
ID: string;
EmployeeName: string;
Experience: string;
Location: string;
}
export default class PnPspCrudWebPart extends BaseClientSideWebPart<IPnPspCrudWebPartProps> {
private AddEventListeners() : void{
document.getElementById('AddItem').addEventListener('click',()=>this.AddItem());
document.getElementById('UpdateItem').addEventListener('click',()=>this.UpdateItem());
document.getElementById('DeleteItem').addEventListener('click',()=>this.DeleteItem());
}
private _getListData(): Promise<ISPList[]> {
return pnp.sp.web.lists.getByTitle("EmployeeList").items.get().then((response) => {
return response;
});
}
private getListData(): void {
this._getListData()
.then((response) => {
this._renderList(response);
});
}
private _renderList(items: ISPList[]): void {
let html: string = '<table class="TFtable" border=1 width=100% style="border-collapse: collapse;">';
html += `<th>EmployeeId</th><th>EmployeeName</th><th>Experience</th><th>Location</th>`;
items.forEach((item: ISPList) => {
html += `
<tr>
<td>${item.ID}</td>
<td>${item.EmployeeName}</td>
<td>${item.Experience}</td>
<td>${item.Location}</td>
</tr>
`;
});
html += `</table>`;
const listContainer: Element = this.domElement.querySelector('#spGetListItems');
listContainer.innerHTML = html;
}
public render(): void {
this.domElement.innerHTML = `
<div class="parentContainer" style="background-color: lightgrey">
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
<div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
<span class="ms-font-xl ms-fontColor-white" style="font-size:28px">Welcome to SharePoint Framework Development using PnP JS Library</span>
<p class="ms-font-l ms-fontColor-white" style="text-align: left">Demo : SharePoint List CRUD using PnP JS and SPFx</p>
</div>
</div>
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
<div style="background-color:Black;color:white;text-align: center;font-weight: bold;font-size:18px;">Employee Details</div>
</div>
<div style="background-color: lightgrey" >
<form >
<br>
<div data-role="header">
<h3>Add SharePoint List Items</h3>
</div>
<div data-role="main" class="ui-content">
<div >
<input id="EmployeeName" placeholder="EmployeeName" />
<input id="Experience" placeholder="Experience" />
<input id="Location" placeholder="Location" />
</div>
<div></br></div>
<div >
<button id="AddItem" type="submit" >Add</button>
</div>
</div>
<div data-role="header">
<h3>Update/Delete SharePoint List Items</h3>
</div>
<div data-role="main" class="ui-content">
<div >
<input id="EmployeeId" placeholder="EmployeeId" />
</div>
<div></br></div>
<div >
<button id="UpdateItem" type="submit" >Update</button>
<button id="DeleteItem" type="submit" >Delete</button>
</div>
</div>
</form>
</div>
<br>
<div style="background-color: lightgrey" id="spGetListItems" />
</div>
`;
this.getListData();
this.AddEventListeners();
}
AddItem()
{
pnp.sp.web.lists.getByTitle('EmployeeList').items.add({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
});
alert("Record with Employee Name : "+ document.getElementById('EmployeeName')["value"] + " Added !");
}
/*
AddItem()
{
pnp.sp.web.lists.getByTitle('EmployeeList').items.add({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
})
.then(addResponse => {
alert("Record with Employee Name : "+ document.getElementById('EmployeeName')["value"] + " Added !");
})
.catch(addError => alert("An error has occurred:" + JSON.stringify(addError)));
}
*/
/*
private AddItem():void
{
pnp.sp.web.lists.getByTitle("EmployeeList").items.add({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location: document.getElementById('Location')["value"]
})
.then((iar: ItemAddResult) => {
console.log(iar);
})
.catch((error:any) => {
console.log("Error: ", error);
});
}
*/
UpdateItem()
{
var id = document.getElementById('EmployeeId')["value"];
pnp.sp.web.lists.getByTitle("EmployeeList").items.getById(id).update({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
});
alert("Record with Employee Name : "+ document.getElementById('EmployeeName')["value"] + " Updated !");
}
DeleteItem()
{
pnp.sp.web.lists.getByTitle("EmployeeList").items.getById(document.getElementById('EmployeeId')["value"]).delete();
alert("Record with Employee ID : "+ document.getElementById('EmployeeId')["value"] + " Deleted !");
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}
Note:
I am referring this link where complete code is available.
https://www.sharepoint-journey.com/SharePoint-Framework-Development-Create-List-CRUD-WebPart-PnPJS.html
Of course you get the alert function to call, because the add/update/delete functions from pnp/sp are asynchronous! you can try that:
pnp.sp.web.lists.getByTitle('EmployeeList').items.add({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
})
.then(addResponse => {
alert("Record with Employee Name : "+ document.getElementById('EmployeeName')["value"] + " Added !");
})
.catch(addError => alert("An error has occurred:" + JSON.stringify(addError)));
I hope this helps, maybe if you get an error here you can update your post to dig deeper into the problem!
Greetings
code has no issue. Best practice should be as mentioend #j.Benda. It seems permission issue.
open in chorme network console (f12 and go to network). it may give u the error which is coming exactly. site url is not set kind. I will try ur code and let u know. try below.
import { default as pnp, ItemAddResult, Web } from "sp-pnp-js";
on button events set web url.
onclickevnet(){
var NewISiteUrl = this.props.siteurl;
var NewSiteUrl = NewISiteUrl.replace("/SitePages", "");
console.log(NewSiteUrl);
let webx = new Web(NewSiteUrl)
webx.lists.getByTitle('EmployeeList').items.add({
EmployeeName : document.getElementById('EmployeeName')["value"],
Experience : document.getElementById('Experience')["value"],
Location:document.getElementById('Location')["value"]
})
.then(addResponse => {
//error
})
.catch(addError => alert("An error has occurred:" + JSON.stringify(addError)));
}
I'm using MVC5 and I want to search for a result and stay at the same page, here is my method in my controller (LiaisonsProjetsPPController) that do the operation of searching :
public ActionResult IndexAjoutML(int id, string SearchString)
{
PartiesPrenantesEntities db = new PartiesPrenantesEntities();
ViewBag.idProjet = id;
ViewBag.searchString = SearchString;
IQueryable<ActivitesPP> qry = this.db.ActivitesPP.Intersect(from item in this.db.LiaisonsProjetsPP where item.idProjet == id select item.ActivitesPP).Include(model => model.Activites.CatActivites);
var act = from s in db.CatActivites
select s;
if (!String.IsNullOrEmpty(SearchString))
return PartialView("~/Views/ActivitesPP/IndexAjoutProjet.cshtml", this.db.ActivitesPP.Where(s => s.PartiesPrenantes.nomPP.Contains(SearchString)).Except(qry));
else
return PartialView("~/Views/ActivitesPP/IndexAjoutProjet.cshtml", this.db.ActivitesPP.Except(qry));
}
Then in my view (Views/ActivitesPP/IndexAjoutProjet) I have my search form and the div of the display result :
#using (Ajax.BeginForm("IndexAjoutML", "LiaisonsProjetsPP", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "search-results"
}, new { #id = "searchFormPP" }))
{
<p>
<label>Partie prenante: </label> #Html.TextBox("SearchString")
<input id="inputRecherche" name="SearchString" type="submit" value="Rechercher" />
</p>
}
<div id="search-results">
#{foreach (var catactivite in Model.GroupBy(model => model.Activites.CatActivites))
{
String couleurCategorie = catactivite.Key.couleurCategorie;
String couleurTexte = CustomHelpers.GetForegroundColor(couleurCategorie);
//Image de la partie prenante
<div class="panel-heading unhide" style="background-image: none; color: #couleurTexte; background-color: #couleurCategorie; padding: 2px;">
</div>
foreach (var pp in catactivite)
{
String nomPP = (pp.idPP == null ? "Inconnu" : pp.PartiesPrenantes.nomPP);
String dateAffichee;
String imgPP = "../../Images/Profils/" + (pp.PartiesPrenantes.imgPP ?? "avatar.png");
if (pp.finActivite == null)
{
dateAffichee = "Depuis le " + String.Format("{0:d/MM/yyyy}", pp.debutActivite);
}
else
{
dateAffichee = "Depuis le " + String.Format("{0:d/MM/yyyy}", pp.debutActivite) + ", jusqu'au " + String.Format("{0:d/MM/yyyy}", pp.finActivite);
}
<div class="panel panel-primary">
<div class="panel-heading unhide" style="color: #couleurTexte; background-color: #couleurCategorie;">
<div style="float: left">
<img class="imgPP img-circle" src="#(imgPP)" />
</div>
<h5>#pp.Activites.libelleActivite (#Html.Raw(pp.idLieu == 999 ? "National" : pp.Lieux.nomLieu))</h5>
<h6>#pp.PartiesPrenantes.nomPP</h6>
</div>
<div class="panel-body hiddenPart">
#if (pp.idPP != null)
{
<label>Commentaire</label>
<p>#(pp.commentaireActivite ?? "Pas plus de détails..")</p>
#Html.Action("CreateForm", "LiaisonsProjetsPP", new { idActivite = pp.idActivite, idProjet = ViewBag.idProjet })
}
</div>
</div>
}
}
}
</div>
}
else
{
#Html.Raw("<p>Aucune partie prenante disponible..")
#Html.Raw("(attention: pour être ajoutée, une partie prenante doit posséder au moins une activité référencée..)</p>")
}
In my view i call my method of search (Views/Projets/Details): #{ Html.RenderAction("IndexAjoutML", "LiaisonsProjetsPP", new { idProjet = Model.idProjet, searchString = Model.searchString }); }
The search work but it redirects me to another page http://localhost:49612/LiaisonsProjetsPP/IndexAjout/1 instead of staying at this page http://localhost:49612/Projets/Details/1.
What you are trying to do seems to be loading results unobtrusively with an AJAX form. The Professional ASP.NET MVC 5 book by John Galloway et al. has a nice section on this, but realizing that no one reads books I will provide a link to a site with a code sample for it.
The .NET Funda site describes here exactly how to search and return the results to the same page without a complete refresh using unobtrusive-ajax.
Likely what you are missing is a reference to jquery.unobtrusive-ajax.min.js. Other posts on Stack Overflow also reference this topic, but I realize you might not know the correct search terms. Try looking further into "AJAX partial view unobtrusive loading" as search terms for further research.
This example is from the book I mentioned from John Galloway.
A JavaScript error message.
function searchFailed(){
$("#searchresults").html("Sorry, there was a problem searching.");
}
This is what a simple Ajax form should look like. Note the "GET" form method.
<div class="panel panel-default">
<div class="panel-heading">
Artist Search
</div>
<div class="panel-body">
#using(Ajax.BeginForm("ArtistSearch", "Home",
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
OnFailure = "searchFailed",
LoadingElementID = "ajax-loader",
UpdateTargetId = "searchresults",
}))
{
<input type="text" name="q" />
<input type="submit" value="search" />
<img id="ajax-loader"
src="#Url.Content("~/Images/ajax-loader.gif")"
style="display:none" />
}
<div id="searchresults"></div>
</div>
</div>
This is the method responsible for returning the partial view:
public ActionResult ArtistSearch(string q)
{
var artists = GetArtists(q);
return PartialView(artists);
}
This is a search method.
public List<Artist> GetArtists(string searchString)
{
return storeDB.Artist.Where(a => a.Name.Contains(searchString)).ToList();
}
Note that the method for returning the partial view is simply "return PartialView(model);"
Can you also tell why sorting don't work with this action:
public function admin_view($id = null)
{
if (!$this->Category->exists($id)) {
throw new NotFoundException(__('Invalid product'));
}
$this->Paginator->settings = array(
'conditions' => array(
'Category.' . $this->Category->primaryKey => $id),
'limit' => $this->limit
);
$this->set('category', $this->paginate('Category'));
}
and view looks this:
<th><?php echo $this->Paginator->sort('price'); ?></th>
<?php foreach ($category[0]['Product'] as $product): ?>
<tr>
<td><?php echo h($product['price']); ?> </td>
</tr>
<?php endforeach; ?>
When I click on price it refresh my page, but sorting not working. Something wrong, I don't know why.
public function view($id = null)
{
if (!$this->Product->exists($id)) {
throw new NotFoundException(__('Invalid product'));
}
$this->Paginator->settings = array(
'conditions' => array(
'Product.' . $this->Product->primaryKey => $id)
);
$this->set('product', $this->paginate('Product');
}