I am trying to use Jeditables (http://www.appelsiini.net/projects/jeditable) in my first castle monorail mvc application
I managed to have the textbox appearing and to the the ajax call, my problem is now that after the ajax call the edited text returs is not changes and i can t get the response after the call
this is my page
<head>
<link href="../../Styles/Main.css" rel="stylesheet" type="text/css" />
<script src="../../JavaScript/jQuery1.4.2.js" type="text/javascript"></script>
<script src="../../JavaScript/EditInLine.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.editable').editable('/Home/Save', {
id : 'editableId',
name : 'editableText',
type : 'textarea',
cancel : 'Cancel',
submit : 'OK',
indicator : '<img src="img/indicator.gif">',
tooltip : 'Click to edit...',
width : '200',
style : 'display: inline',
callbac : function(value, settings) {
alert(value);
return value;
}
});
});
</script>
</head>
<body>
<label id='1' class='editable '>Some text</label>
</body>
</html>
and this my controller
using Castle.MonoRail.Framework;
using System;
using EditInLine.Model.Interfaces;
using EditInLine.Model;
namespace EditInLine.Controllers
{
[Layout("Default"), Rescue("Default")]
public class HomeController : SmartDispatcherController
{
private EditableElement editableElement;
private EditableElement EditableElement
{
get
{
if (Session["EditableElement"] == null)
{
Session["EditableElement"] = new EditableElement { Id = 1, Text = "Some text", CssClass = "editable" };
}
return (EditableElement)Session["EditableElement"];
}
}
public void Index()
{
PropertyBag["IsAdmin"] = true;
PropertyBag["element"] = EditableElement;
}
public void Save()
{
var elementId = Convert.ToInt32(Request.Form["editableId"]);
var text = Request.Form["editableText"];
var element = new EditableElement { Id = elementId, CssClass = "editable", Text = text };
Session["EditableElement"] = element;
}
}
}
thanks for you help
The problem with Save() was that you did not return a string to the browser. Easily fixed with RenderText() call. You should also be using parameter binding instead of messing with Request.Form:
public void Save(int editableId, string editableText)
{
var element = new EditableElement { Id = editableId, CssClass = "editable", Text = editableText};
Session["EditableElement"] = element;
RenderText(editableText);
}
I found the solution
public void Save()
{
var elementId = Convert.ToInt32(Request.Form["editableId"]);
var text = Request.Form["editableText"];
var element = new EditableElement { Id = elementId, CssClass = "editable", Text = text };
Session["EditableElement"] = element;
Response.Write(text);
CancelView();
}
Related
Hope all of you fine and doing well.
I am using multi select bootstrap drop down jquery. I am using asp.net core to populdate Listbox, its working fine for selection,select all etc.
But i want that when i select element from Dropdown A then this element must be removed from dropdown B and if i unselect element from dropdown A then it must added/show in dropdownB. And vice virsa as well, if element selected in dropdown B then this element removed from dropdownA, also if select all from dropdownA then all elements removed from dropdownB and vice virsa as well.
Hope you understand guys.
For example: If A,B,C,D values in dropdownlistA and if i select A then it must be disable or hide from dropdownB,if i select all then must remove all from dropdownB, and also vice virsa for dropdownB as well,
Note: DropdownA and DropdownB both have same number of values/elements,same text ,same value,
View
#section AddToHead{
<link rel="stylesheet" href="~/css1/bootstrap-3.1.1.min.css" type="text/css" />
<link rel="stylesheet" href="~/css1/bootstrap-multiselect.css" type="text/css" />
<script type="text/javascript" src="https://code.jquery.com/jquery-1.8.2.js"></script>
<script type="text/javascript" src="~/js1/bootstrap-2.3.2.min.js"></script>
<script type="text/javascript" src="~/js1/bootstrap-multiselect.js"></script>
}
<form class="column" asp-controller="group" asp-action="createresult" style="height:100%;" method="post">
<span class="column" style="height:50px;">
#Html.ListBoxFor(x => x.AvailablePlayers, Model.AvailablePlayers, new { id = "PlayersTeamA", onChange = "getSelectedOptions(this)", multiple = "multiple" })
#Html.ValidationMessageFor(model => model.TeamOnePlayers)
</span>
<span class="column">
#Html.ListBoxFor(x => x.AvailablePlayers, Model.AvailablePlayers, new { id = "PlayersTeamB", onChange = "getSelectedOptions(this)", multiple = "multiple" })
#Html.ValidationMessageFor(model => model.TeamTwoPlayers)
</span>
</form>
</div>
#section Scripts {
<script type="text/javascript">
$(function () {
$('#PlayersTeamA').multiselect({
includeSelectAllOption: true
});
$('#PlayersTeamB').multiselect({
includeSelectAllOption: true
});
});
function getSelectedOptions(sel) {
var idddl = sel.id;
var opts = [],
opt;
var len = sel.options.length;
for (var i = 0; i < len; i++) {
opt = sel.options[i];
if (opt.selected) {
opts.push(opt);
var idul = sel.id;
alert(idul);
var ul = document.getElementById(idul);
ul.removeChild(ul.childNodes[1]);
}
}
return opts;
}
Here is a working demo like below:
#model Players
<form class="column" asp-controller="group" asp-action="createresult" style="height:100%;" method="post">
<div id="A">
<span class="column" style="height:50px;">
#Html.ListBoxFor(x => x.AvailablePlayers, Model.AvailablePlayers, new { id = "PlayersTeamA", multiple = "multiple" })
</span>
</div>
<div id="B">
<span class="column">
#Html.ListBoxFor(x => x.AvailablePlayers, Model.AvailablePlayers, new { id = "PlayersTeamB", multiple = "multiple" })
</span>
</div>
</form>
#section Scripts {
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/js/bootstrap-multiselect.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css"/>
<script>
$(function () {
$('#PlayersTeamA').multiselect({
includeSelectAllOption: true
});
$('#PlayersTeamB').multiselect({
includeSelectAllOption: true
});
});
var data = [];
$('#B option').each(function (index, item) {
data.push({ label: this.label, value: this.value });
});
$("#PlayersTeamA").change(function () {
var selectedText = $('#PlayersTeamA').val();
var newData = data;
selectedText.forEach(function (element, index, array) {
newData = newData.filter(function (el) { return el.value != element; });
});
$("#PlayersTeamB").multiselect('dataprovider', newData);
});
</script>
}
My testing model:
public class Players
{
public SelectList AvailablePlayers { get; set; }
}
public class AvailablePlayer
{
public int Id { get; set; }
public string Name { get; set; }
}
My testing controller:
[HttpGet]
public async Task<IActionResult> Index()
{
var player = new List<AvailablePlayer>()
{
new AvailablePlayer(){ Id=1,Name="aa"},
new AvailablePlayer(){ Id=2,Name="bb"},
new AvailablePlayer(){ Id=3,Name="cc"}
};
var model = new Players()
{
AvailablePlayers = new SelectList(player, "Id", "Name")
};
return View(model);
}
Result:
It appears you are using bootstrap's multiselect. In the documentation, we can see that you can configure data as follows (after executing .multiselect on particular input, as you do in your sample):
var data = [
{label: "Messi", value: "Messi"},
{label: "Ronaldo", value: "Ronaldo"}
];
$("#PlayersTeamA").multiselect('dataprovider', data);
Now, attach to 'onchange' event of #PlayersTeamA and update the available data for #PlayersTeamB, for example like this:
$("#PlayersTeamA").change(function () {
var selectedText = $(this).find("option:selected").text();
var newData = data.filter(function(el) { return el.value == selectedText; });
$("#PlayersTeamB").multiselect('dataprovider', newData);
});
You have to attach to onchange of #PlayersTeamB as well, I believe (so that it works in both directions).
I have a functionality where I append a select html when a button is clicked using jQuery. I already have a select which uses a asp-item tag helper to fill it with my corresponding model. The platform I'm using is asp-net core 2.2 and I'm using a razor page for my page.
My question is how do I edit my jQuery so that when I clicked the button, the asp-item is already loaded into the select?
Here is my jQuery code:
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$(".addselection").append('<div> <select class="form-control" name="[' + (tc) + '].DriverID" asp-for="TripDrivers.DriverID" asp-items="Model.DriverList" > <option value = ""> Select a driver </option></select></div>')
});
and this is my OnGet to load the items
public IActionResult OnGet()
{
DriverList = _context.Drivers.Select(a =>
new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName
}).ToList();
}
This is my first ever question, so please bear with me if there are any grammatical errors or missing information. I'll add them if necessary.
EDIT: Here is the design I'm trying to do.
Once the plus button is clicked. It should add a row of dropdownlist each with the option being loaded from the list on the OnGet method.
ANOTHER EDIT: As per user #itminus instructions, I've created a one sample page and a partial view to apply the code given below.
Here is what my FirstPage.cshtml looks like
#page
#model MasigasigTrackingSystem.Pages.TestingPages.FirstPageModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>FirstPage</title>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script>
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList', {
method: "GET",
data: { tc: tc },
success: function (d) { $(".addselection").append(d); }
});
});
</script>
</head>
<body>
<button id="AddButton" class="btn" type="button">+</button>
#*<select asp-for="Mode" asp-items="Model.DropdownListViewModel.Drivers" class="form-control">
<option value="">Select a driver</option>
</select>*#
<div class="addselection">
<partial name="_SecondPage.cshtml" />
</div>
</body>
</html>
My FirstPageModel
namespace MasigasigTrackingSystem.Pages.TestingPages
{
public class FirstPageModel : PageModel
{
private readonly MasigasigTrackingSystem.Data.ApplicationDBContext _context;
public FirstPageModel(MasigasigTrackingSystem.Data.ApplicationDBContext context)
{
_context = context;
}
[BindProperty]
public Drivers Drivers { get; set; }
public List<SelectListItem> DriverList { get; set; }
[BindProperty]
public DropdownListViewModel DropdownListViewModel { get; set; }
public void OnGet()
{
DriverList = _context.Drivers.Select(a =>
new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName
}).ToList();
DropdownListViewModel = new DropdownListViewModel();
DropdownListViewModel.Drivers = DriverList;
}
public IActionResult OnGetDropdownListAsync(int tc)
{
var list = _context.Drivers.Select(a => new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName,
}).ToList(); // or filter by Where( ... tc...).ToList()
return Partial("/Pages/TestingPages/_SecondPage.cshtml", new DropdownListViewModel
{
Drivers = list,
ID = tc,
});
}
}
}
My partial _SecondPage
#using MasigasigTrackingSystem.Models
#model DropdownListViewModel
<div>
<select class="form-control dropdown" name="[#Model.ID].DriverID" asp-items="#Model.Drivers">
<option> Select a driver </option>
</select>
</div>
My DropdownlistViewModel
namespace MasigasigTrackingSystem.Models
{
public class DropdownListViewModel
{
public int ID { get; set; }
public IList<SelectListItem> Drivers { get; set; }
}
}
Here's a demo that gets the partial view dynamically from server.
Create a Handler OnGetDropdownListAsync(int tc) in your PageModel:
public class YourPageModel : PageModel
{
... other handler methods, e.g. OnGet() render the Index
public IActionResult OnGetDropdownListAsync(int tc)
{
var list = _context.Drivers.Select(a =>new SelectListItem{
Value = a.ID.ToString(),
Text = a.FullName,
}).ToList(); // or filter by Where( ... tc...).ToList()
return Partial( "/Pages/Shared/Selection.cshtml" , new DropdownListViewModel{
Drivers = list,
Index = tc,
});
}
}
Here the DropdownListViewModel is a plain ViewModel that holds the data:
public class DropdownListViewModel{
public IList<SelectListItem> Drivers{get;set;}
public int Index {get;set;}
}
Move your original html snippet within jQuery into a new partial view file: /Pages/Shared/Selection.cshtml
#using App.Pages
#model DropdownListViewModel
<div>
<select class="form-control dropdown" name="[#Model.Index].DriverID" asp-items="#Model.Drivers">
<option> Select a driver </option>
</select>
</div>
Finally, change your JavaScript to send an ajax request and update the UI in following way:
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList',{
method:"GET",
data:{ tc: tc },
success:function(d){ $(".addselection").append(d); }
});
});
[Edit]
You are passing currect ViewData to <partial> implicitly, which leads to this type error. You need change it to :
<partial name="/Pages/TestingPages/_SecondPage.cshtml" model="#Model.DropdownListViewModel" />
You're referencing an slim jQuery that doesn't have a ajax. Please change the script to <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>.
You're binding an event for #AddButton before this element has been created. You need wrap the js into a $(document).ready(function(){ .... }. You can also create a manually script after the #AddButton element. Or put the <script> into #section Scripts{} if you're using a default Layout which will make the script take effect after the page has been loaded.
Also you didn't initialize a tc variable.
In short, you need fix the bugs as below:
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
var tc = 0;
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList', {
method: "GET",
data: { tc: tc },
success: function (d) { $(".addselection").append(d); }
});
});
});
</script>
...
<div class="addselection">
<partial name="/Pages/TestingPages/_SecondPage.cshtml" model="#Model.DropdownListViewModel" />
</div
in Bridge.net i can only create a defult eventlistner.
In javascript i will do it like this.
<div id="nose" onclick="Test(this);"></div>
<script>
function Test(htmlelement) {
var id = htmlelement.id;
console.log('area element id = ' + id);
}
</script>
I fixed that this way.
public Static void SomeFunc(){
var label = new HTMLLabelElement();
label.TextContent = txtbox.Value;
label.Style.FontSize = "40px";
label.AddEventListener(EventType.Click,ClickEvent );
}
public static void ClickEvent (Event e)
{
var x = (HTMLElement)e.Target;
x.SetAttribute("value", "HelloWorld");
}
Controller:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ExperimentalController : Controller
{
public ActionResult ReloadTest1()
{
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
return View();
}
public PartialViewResult ReloadTest1Partial()
{
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
return PartialView();
}
}
View:
#{
ViewBag.Title = "ReloadTest1";
string time = this.ViewBag.Time;
ViewData["date"] = time;
ViewBag.TheTitle = "test";
}
<h2>ReloadTest1</h2>
<select id="iSelect" name="iSelect" >
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", null, new ViewDataDictionary { {"vb", ViewBag}});}
</div>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$('#iSelect').on('change', function () {
$("#myPartialViewContainer").load('#(Url.Action("ReloadTest1Partial", "Experimental", null, Request.Url.Scheme))')
})
</script>
Partial View:
#{
var vb = ((dynamic)ViewData["vb"]);
}
<div>
<span>#vb.Time</span>
</div>
What is not working:
Passing the viewbag/viewdata directly from controller to partial view because mvc does not accept that to happen.
What is working:
from the above code you can see that the partial view gets the data ONCE with the Html.RenderPartial method and the viewbag passing down.
the reload does work on change of the selected object in the dropdown
What is needed:
I need to pass data to the partial view when it is reloaded or afterwards, this is mainly a test setup but i finally want to be able to update tables dependant on the select value.
If somone is able to give me a working example please do so.
In your controller you;re using ViewBag to set custom value, but in your view you are working with ViewData as well as referring to a different name (you're setting ViewBag's Time property in controller, but you expect ViewData's vb property in the view).
Change your view to expect model`:
#model MyModel
#{
string time = "";
if (ViewData["Time"] != null)
{
time = ViewData["Time"];
}
}
<div>
<span>#Model.Time</span>
</div>
And change you controller to pass it:
public ActionResult ReloadTest1()
{
var model = new MyModel {Time = DateTime.Now.ToString()};
return View(model);
}
public PartialViewResult ReloadTest1Partial()
{
var model = new MyModel {Time = DateTime.Now.ToString()};
return PartialView(model);
}
And you master view file will look like this:
#model MyModel
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", model);}
</div>
And create your model:
public class MyModel
{
public string Time {get;set;}
}
As a side not, it's always preferable to use a strongly-typed model instead of ViewBag or ViewData as you can get compilation errors and IntelliSense
Final solution:
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
namespace RolloutTool.Controllers
{
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ExperimentalController : Controller
{
public ActionResult ReloadTest1()
{
var model = new RolloutTool.Models.ExperimentalViewModels.MyModel { Time = DateTime.Now.ToString() };
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
ViewData["Time"] = temp;
return View(model);
}
[HttpPost]
public PartialViewResult ReloadTest1Partial(string test)
{
var model = new RolloutTool.Models.ExperimentalViewModels.MyModel { Time = DateTime.Now.ToString() };
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
ViewData["Time"] = temp;
return PartialView("_ReloadTest1Partial", model);
}
// GET: Experimental
public ActionResult Experimental()
{
ViewBag.Message = "Your contact page.";
ViewBag.TestValue = 10;
string[] temp = { "alpha", "beta", "gamma", "delta" };
ViewBag.names = temp;
int temp2 = temp.Length;
ViewBag.nameslength = temp2;
return View();
}
}
}
View:
#{
ViewBag.Title = "ReloadTest1";
string time = this.ViewBag.Time;
ViewData["date"] = time;
ViewBag.TheTitle = "test";
}
#model RolloutTool.Models.ExperimentalViewModels.MyModel
<h2>ReloadTest1</h2>
<select class="chosen-select" id="iSelect" name="iSelect">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", Model);}
</div>
#Styles.Render(
"~/content/chosen/chosen.css",
"~/content/chosen/prism.css",
"~/content/chosen/style.css",
"~/content/bootstrap.css",
"~/content/Site.css")
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
<script>
var config = {
'.chosen-select': {},
'.chosen-select-deselect': { allow_single_deselect: true },
'.chosen-select-no-single': { disable_search_threshold: 10 },
'.chosen-select-no-results': { no_results_text: 'Oops, nothing found!' },
'.chosen-select-width': { width: "95%" }
}
for (var selector in config) {
$(selector).chosen(config[selector]);
}
</script>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$('#iSelect').on('change', function () {
getPartial();
})
</script>
<script>
function getPartial() {
var tempSelect = document.getElementById("iSelect");
var tempResult = tempSelect.options[tempSelect.selectedIndex].text;
$.ajax({
url: "ReloadTest1Partial",
type: "POST",
data: {'test' = tempResult}, //if you need to post Model data, use this
success: function (result) {
$("#myPartialViewContainer").html(result).find("select").each(function () {
$(this).chosen({});
}
});
}
</script>
#{
string time = "";
string temp = "";
if (ViewData["vb"] != null)
{
temp = "1";
time = ((dynamic)ViewData["vb"]).Time;
}
else if (ViewContext.Controller.ViewBag.Time != null)
{
temp = "2";
time = ViewBag.Time;
}
else if (ViewData["Time"] != null)
{
temp = "3";
time = (string) ViewData["Time"];
}
}
#model RolloutTool.Models.ExperimentalViewModels.MyModel
<div>
<span>#time</span>
<span>#Model.Time</span>
<span>#temp</span>
</div>
<select class="chosen-select"></select>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
This updates the partial view correctly AND reloads the chosen-select dropdowns. (see styles and scripts not working in partial view)
I am developing a visualforce page for force.com site. I am using apex command link for do some action. the code is given below:
<ul>
<li class="pill-none"><span>
<apex:commandLink action="{!processOnSelected}" reRender="windowOpenPanel">Print
<apex:param name="commandAtt" value="print"/>
</apex:commandLink>
</span>
<apex:outputPanel id="windowOpenPanel">
<apex:outputPanel rendered="{!isOpen}">
<script type="text/javascript">
window.open('http://invoicedetails.dev.cs16.force.com/EnterCode/InvoicePDF?invoiceId={!idString}');
</script>
</apex:outputPanel>
</apex:outputPanel>
</li></ul>
but is not going to class method processOnSelected(). It is giving js error
actionUrl.indexOf is not a function
below is my controller method code:
public void processOnSelected () {
String command = Apexpages.currentPage().getParameters().get('commandAtt');
idString = '';
isOpen=true;
Set<Id> selectedIdSet = new Set<Id>();
if (command=='print' || command=='payment') {
//wfdList = new List<WrapForDescription>();
//System.debug('__wfdList__'+wfdList);
for(WrapForDescription tmpList : wfdList) {
if(tmpList.checked) {
//WrapForDescription selected = new WrapForDescription();
//selected.wrapOpp = tmpList.wrapOpp;
//wfdList.add(selected);
selectedIdSet.add(tmpList.wrapOpp.Id);
idString+= tmpList.wrapOpp.Id+',';
//System.debug('__True__');
}
}
idString = idString.substring(0, idString.length()-1);
}
else if (command=='onePDF') {
idString = id;
}
Blob idBlob = Blob.valueOf(idString);
idString = Encodingutil.base64Encode(idBlob);
System.debug('__idString__'+idString);
System.debug('__selectedIdSet__'+selectedIdSet);
if (command=='payment') {
page = 'beforePaymentAll';
AggregateResult oppSumAmount = [select SUM(Amount) total from Opportunity where Id IN :selectedIdSet];
//accObj = [select Name, convertCurrency(Unpaid_Opportunity_Amount__c), convertCurrency(Paid_Opportunity_Amount__c) from Account where Id =:accId];
unpaid_amount = (Decimal)oppSumAmount.get('total');
oppList = [Select Id, Name, convertCurrency(Opportunity.Amount), Opportunity.CloseDate, Opportunity.CurrencyIsoCode, Opportunity.SecretCode__c From Opportunity o where Id IN :selectedIdSet order by CloseDate desc];
oppListSize = oppList.Size();
System.debug('__oppLineList__'+oppList);
isOpen=false;
}
}
This is the JS file which is giving error:
http://invoicedetails.dev.cs16.force.com/faces/a4j/g/3_3_3.Finalorg.ajax4jsf.javascript.AjaxScript?rel=1339862070000
and error is giving in this line
var ask=actionUrl.indexOf('?')
what is wrong in my code. anybody please help me.
Please, post a controller code for processOnSelected method.
I can assume that this method doesn't have params or it is private.
Try to change
public void processOnSelected() {
...
}
to
public PageReference processOnSelected(string commandAtt) {
...
return null;
}