Not able to get desired output for the following code - apex

outputimage
.JS file
import { LightningElement, wire } from 'lwc';
import getContactList from '#salesforce/apex/ContactController.getContactList';
export default class ApexWireMethodToFunction extends LightningElement {
contacts;
error;
#wire(getContactList)
wiredContacts({ error, data }) {
if (data) {
this.contacts = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.contacts = undefined;
}
}
}
HTML file:
<template>
<lightning-card
title="ApexWireMethodToFunction"
icon-name="custom:custom63"
>
<div class="slds-var-m-around_medium">
<template if:true={contacts}>
<template for:each={contacts} for:item="contact">
<p key={contact.Id}>{contact.Name}</p>
</template>
</template>
<template if:true={error}>
<c-error-panel errors={error}></c-error-panel>
</template>
</div>
<c-view-source source="lwc/apexWireMethodToFunction" slot="footer">
Call an Apex method that retrieves a list of records using #wire. In
this recipe, the Apex method is #wired to a component function.
</c-view-source>
</lightning-card>
</template>
APEX CLASS- CONTACTCONTROLLER
#AuraEnabled(cacheable=true)
public static List<Contact> getContactList() {
return [
SELECT
Id,
Name,
FirstName,
LastName,
MailingAddress
FROM Contact
WHERE Name != NULL
WITH SECURITY_ENFORCED
LIMIT 10
];
}
}
This is actually a code copy pasted from GitHub: 'LWC Recipes'--apexWireMethodToFunction LWC component.
But in HTML file, I have made small change. I have removed the line which has the reference for error-panel component and rest of the code is the same.
When I tried to deploy this code in my system I am getting the attached image as output. I am not sure as to why am I getting output as some undefined data.
Please help.

My best bet would be your user profile doesn't have access to the apex class. Thus the component is displaying the error part. As we don't see the error component code, it's hard to help you more.
You could use the browser devtool, go to network tab and search for your apex method call and see what is the raw answer from the server.

Related

ReferenceInput Select Input for Filter component Form

I built a custom Filter component for my List View and Im having trouble populating a Select Input of ALL available options for a property. for instance
<Form onSubmit={onSubmit} initialValues={filterValues} >
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<ReferenceInput label="Ring Id" source="ringid" reference="candidates">
<SelectInput optionText="ringid" />
</ReferenceInput>
</form>
)}
</Form>
Without building a "getMany" dataProvider Im told that I can access all of the (2,000+ ids) "ringid"s pulled in from the "getList" provider and list every ID into the SelectInput field and search in my custom Filter component.
Issues presented:
I have to hard code amount of results I can have (Default 25)
When I submit the form to Search through the filter component "Associated reference no longer appears to be available." appears and the search fails.
The "getMany" component is only half way built but it seems that ReferenceInput only wants to use "getMany"(Im told that building the backend and building code to use getMany is not an priority to build so I cant build it myself)
25 Populated IDs Screenshot
Form Error when Filter is submitted ScreenShot
So I would like some help in the right direction to populate a SelectInput of all available ids in the getList dataProvider and be sure that I can even use this input in my Filter form component. Thank you in advance for any feedback.
1: Yes, i think there's no option to add pagination to ReferenceInput, you must hardcode it, but, if your backend already supports text search, you can use an AutocompleteInput as child, allowing users to filter results:
<ReferenceInput
label="Ring Id"
source="ringid"
reference="candidates"
filterToQuery={searchText => ({ paramNameThatYourBackendExpects: searchText })}
>
<AutocompleteInput optionText="ringid" />
</ReferenceInput>
2 & 3: 2 happens because of 3. ReferenceInput only "wants" to use getMany because it also support SelectManyInput as child, for such case, it's better to get all selected options at once, than calling one by one, so, to make code simpler, ReferenceInput always use getMany. If you can't implement backend part of getMany, but can add code to your dataProvider, you can implement getMany by making multiple getOne calls:
Assuming a v3 dataProvider:
this.getMany = async (resource, params) => {
const response = {data: []}
for (const id of params.id) {
response.data.push(await this.getOne(resource, {id}))
}
return response
}
v2 is implementation-dependant, just follow the same principle.
If you can't change the dataProvider, e.g, a third-party available dataProvider, you can wrap it:
v3
const fakeGetManyDataProvider = dataProvider => ({
...dataProvider,
getMany: async (resource, params) => {
const response = {data: []}
for (const id of params.id) {
response.data.push(await dataProvider.getOne(resource, {id}))
}
return response
}
})
v2
import { GET_MANY, GET_ONE } from 'react-admin'
const fakeGetManyDataProvider = dataProvider => async (verb, resource, params) => {
if (verb === GET_MANY) {
const response = {data: []}
for (const id of params.id) {
response.data.push(await dataProvider(GET_ONE, resource, {id}))
}
return response
}
return dataProvider(verb, resource, params)
}
Please note that error handling is omitted for simplicity, react admin expects rejecteds promise instead of unhandled expections, so you must handle errors.

Jade + mongodb + express.js, delete form not working

My delete code is not working and I think not even firing as I don't see my console.log, I have an add button that works with a form and they look alike, this is why I don't get it.
app.js:
var db = monk('localhost:27017/mongodb');
Jade:
extends admin_menu
block content
h1.
Cocktail list
ul
each cocktail, i in cocktaillist
li
p= cocktail.name
form#form_delete_project(name="/admin/delete_cocktail", method="post", action="/admin/delete_cocktail")
input#input_name(type="hidden", placeholder="", name="_id", value="#{cocktail._id}")
button#submit_project(type="submit") delete
index.js:
router.post('/admin/delete_cocktail', function(req, res) {
console.log(id)
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var id = req.body._id;
// Set our collection
var collection = db.get('cocktailcollection');
// Submit to the DB
collection.remove({
"_id":id
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem removing the information to the database.");
}
else {
// And forward to success page
res.redirect("/admin/cocktail_list");
}
});
});
Jade is built on indentation. Since you are not indenting the items in your form it is not in you form. In html your code would look like this:
<form>
</form>
<input name="_id">
<button>
Since your input with _id is outside the form it is not being posted. That is why your console log is showing nothing. There is no req.body._id.And, of course, your submit-button is also outside the form. So it does nothing.
So, the first thing you should do is indent the code.

Umbraco cannot find the route in backoffice

I've used Umbraco 7.3 in my project. I created a custom data type but when I want to call a Surfacecontroller in here is HelloSurfaceController or Hello2SurfaceController, I got an error in umbraco backoffice that said Request error: The URL returned a 404 (not found):
I studied some articles about routing but I couldn't solve my problem. I don't know that where I did wrong.
How can I solve this problem?
Reply.controller.js:
angular.module("umbraco")
.controller("Reply.controller", function ($scope, $http) {
$scope.SendReply = function () {
var sendTo = $("#Email").val();
var textMessage = $("#TextMessage").val();
$scope.xxx = "I'm here!";
var data = { SendTo: sendTo, TextMessage: textMessage };
// ~/Hello2Surface/ReplyMessage ---> Cannot find this URL
$http.post("~/App_Plugins/Reply/HelloSurface/ReplyMessage") // Can not find this URL
.then(function (response) {
alert("YES!");
//TODO:
});
}
});
SurfaceController
namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
{
public class HelloSurfaceController : SurfaceController
{
[HttpPost][ChildActionOnly]
public ActionResult ReplyMessage()
{
//TODO: how should be write this method that be proper for getting data from angularjs?
return null;
}
}
}
package.manifest
{
propertyEditors: [
{
alias: "Send.Reply",
name: "Send Reply",
editor:{
view:"~/App_Plugins/Reply/Reply.html"
},
}
]
,
javascript:[
'~/App_Plugins/Reply/Reply.controller.js'
]
}
Reply.html
<div ng-controller="Reply.controller">
<div style="width: 100%;">
<input type="button" value="Send Reply" title="SendReply" name="Send Reply" ng-click="SendReply()" />
</div>
<div>
<input type="text" ng-model="xxx" name="message" />
</div>
Error in umbraco backoffice:
Take a closer look at the documentation - in particular the Plugin-based SurfaceControllers section:
https://our.umbraco.org/documentation/Reference/Routing/surface-controllers
try doing this (note the PluginController attribute):
namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
{
[PluginController("Reply")]
public class HelloSurfaceController : SurfaceController
{
[HttpPost][ChildActionOnly]
public ActionResult ReplyMessage()
{
//TODO: how should be write this method that be proper for getting data from angularjs?
return null;
}
}
}
Other Notes:
You don't need to include "Surface" in the controller name anymore - simply calling it HelloController is enough.
Don't use a SurfaceController for Api calls if you're using it with AngularJS - Better to use an UmbracoApiController instead. Check out https://our.umbraco.org/documentation/Reference/Routing/WebApi/ for more information (including notes on where to expect the Api Endpoint to be)
You might also want to re-locate your controller so it's in a more conventional spot. There's no problem with putting it in the ~/Controllers directory even if it is a Plugin Controller.
Edit: Added "correct" way to do this:
As noted above, to implement an UmbracoApiController, you want a class looking like this - note you can use UmbracoApiController if you don't need to worry about authorization:
namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
{
[PluginController("Reply")]
public class HelloApiController : UmbracoAuthorizedApiController
{
public void PostReplyMessage(string to, string message)
{
// TODO: process your message and then return something (if you want to).
}
}
}
Then in AngularJS set up a resource like this:
function replyResource($q, $http, umbDataFormatter, umbRequestHelper) {
var replyResource = {
sendMessage: function (sendTo, msg) {
return umbRequestHelper.resourcePromise(
$http.post("Backoffice/Reply/HelloApi/PostReplyMessage?" +
umbRequestHelper.dictionaryToQueryString(
[{ to: sendTo }, { message: msg }])),
'Failed to send message to ' + sendTo + ': ' + msg);
}
};
return replyResource;
}
angular.module('umbraco.resources').factory('replyResource', replyResource);
and finally your actual view controller can use this as follows:
angular.module("umbraco")
.controller("Reply.controller", function ($scope, $http, $injector) {
// Get a reference to our resource - this is why we need the $injector specified above
replyResource = $injector.get('replyResource');
$scope.SendReply = function () {
// You really shouldn't use jQuery here - learn to use AngularJS Bindings instead and bind your model properly.
var sendTo = $("#Email").val();
var textMessage = $("#TextMessage").val();
replyResource.sendMessage(sendTo, textMessage)
.then(function (response) {
// Success
}, function (err) {
// Failure
});
}
};
});
It's possible there's some errors in there; I did it mostly from memory - in particular, you may need to look into the best way to post data to the ApiController - it's not likely that it'll just accept the two parameters like that.
For a more complete example, consider reviewing the code of the Umbraco MemberListView plugin: https://github.com/robertjf/umbMemberListView
Also, you really should read up on the ASP.Net MVC fundamentals and the Umbraco Documentation for SurfaceControllers and APIControllers I've listed above already.
remove the "Surface" from the URL and include "backoffice":
angular.module("umbraco")
.controller("Reply.controller", function ($scope, $http) {
$scope.SendReply = function () {
var sendTo = $("#Email").val();
var textMessage = $("#TextMessage").val();
$scope.xxx = "I'm here!";
var data = { SendTo: sendTo, TextMessage: textMessage };
// ~/Hello2Surface/ReplyMessage ---> Cannot find this URL
$http.post("backoffice/Reply/Hello/ReplyMessage") // Can not find this URL
.then(function (response) {
alert("YES!");
//TODO:
});
}
});
Also, I'd recommend using UmbracoAuthorizedController not a surface controller as this is being used in the back end by logged in users it'll be wise to keep it secure.
So instead your controller should look something like this:
[PluginController("Reply")]
namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
{
public class HelloApiController : UmbracoAuthorizedJsonController
{
public [Model-to-be-returned-to-angular] ReplyMessage()
{
//sql query etc to populate model
//return model
}
}
}

Asp.NET MVC Razor DropDownList and document with table part

I need to make a drop-down list box, which selects data from the related table.
I've used an example from MSDN, but it doesn't work.
public ActionResult Create()
{
TypeItemsDropDownList();
return View(new Item());
}
//
// POST: /Item/Create
[HttpPost]
public ActionResult Create([Bind(Include = "idItem,nameItem,priceItem,quantity,inStock,descrItem,idTypeItem")]Item item)
{
try
{
if (ModelState.IsValid)
{
iac.StoreNewItem(item);
return RedirectToAction("Index");
}
}
catch (System.Data.DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
TypeItemsDropDownList(item.idTypeItem);
return View(item);
}
private void TypeItemsDropDownList(object selectedTypeItem = null)
{
cabproddbEntities db = new cabproddbEntities();
var typeQuery = from d in db.TypeItem
orderby d.nameTypeItem
select d;
ViewBag.idTypeItem = new SelectList(typeQuery, "idTypeItem", "nameTypeItem", selectedTypeItem);
}
The error occurs here:
<div class="editor-label">
<label class="control-label col-md-2" for="idTypeItem">Тип продукции</label>
</div>
<div class="editor-field">
#Html.DropDownList("idTypeItem", String.Empty)
#Html.ValidationMessageFor(model => model.idTypeItem)
</div>
on this line: #Html.DropDownList("idTypeItem", String.Empty)
The table TypeItem has the data.
The thrown exception is: System.Data.EntityCommandExecutionException with the following details:
The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.
Your issue is you are not linking your SelectList to the drop down. Use the DropDownListFor() helper and reference your select list in it. As shown below.
Your naming conventions are a little off also and this might be leading you into confusion.
#Html.DropDownListFor(m => Model.selectedItem, ViewBag.idTypeItem)

ajaxcontroltoolkit setting hidden value after asyncfileupload has completed

I have an asyncfileupload control that I'm using from the ajaxcontroltoolkit. On the file complete in the code behind I process the file and write the information in the file to a database. I get the id of the record from the database, and this needs to be written to an asp hidden field. I've tried just setting the value:
fldImageID.Value = pimg.IdImageGroup.ToString();
I've tried Registering a script like I've seen in an example on a website:
ScriptManager.RegisterClientScriptBlock(
ImageFileUploader,
ImageFileUploader.GetType(),
"script1",
"alert('hi'); top.document.getElementById('"
+ fldImageID.ClientID
+ "').value='"
+ pimg.IdImageGroup.ToString()
+ "'; top.document.getElementById('"
+ lblError.ClientID
+ "').innerHTML = 'image uploaded'",
true);
I've just tried embedding javascript in a response.Write call from the method I've set to process the uploaded file. Nothing I've done has worked so far. After I've done everything the hidden field still does not contain the required value.
This is pretty easy with jQuery. Have an html hidden input control placed in your page, not the asp:hidden input control. Add a class lets say "hiddenPhoto" to your html hidden control.
so lets say our control html is like this
<input type="hidden" class="hiddenPhoto" runat="server" id="hdPhotoName" />
Now access it using class selector in your OnClientUploadComplete js method and set its value. Have it declared runat="server" in order to access its value on the server side.
Regards
I found an acceptable solution back when I was working on this. And since then I've received emails from people who have had the same problem and have been asking if I found a solution. So I'm presenting it here, stripping out any extraineous code:
From the user control that has the FileUpload control I first set the session variable on the back side in the FileUploadComplete handler:
*in the ascx file (upload_chart.ascx) I have the AsyncFileUpload, what is important is the OnUploadComplete and the OnClientUploadComplete:*
<ajaxToolkit:AsyncFileUpload
OnUploadedComplete="FileUploadComplete1"
OnClientUploadComplete="UploadComplete1"
ID="ImageFileUploader"
runat="server" />
*in the code behind of the ascx file (upload_chart.ascx.cs) I handle the FileUploadComplete:*
public void FileUploadComplete1(object sender, EventArgs e)
{
try
{
if (ImageFileUploader.FileBytes.Length > 0)
{
// File data is in ImageFileUploaded.FileBytes
// Save it however you need to
// I saved it to a database, in a DBImage Object class I created
// DBImage is specific to my application
ODS.Entity.DBImage pimg =
ODS.Data.DataRepository.SaveImageBytes(ImageFileUploaded.FileBytes);
// Set the ImageID1 in the session
Session["ImageID1"] = pimg.IdImageGroup.ToString();
}
else
{
// error handling for an empty file, however you want to handle it
}
}
catch (Exception Ex)
{
// error handling for an unhandled exception, whatever you want to do here
}
}
Javascript and script methods are used to set the value on the page, here is my codebehind for the script method:
// on the aspx page code behind (chartofthedayadmin.aspx.cs) I have the webmethod:
[System.Web.Services.WebMethod]
public static string GetImageID1()
{
System.Web.SessionState.HttpSessionState Session = System.Web.HttpContext.Current.Session;
String retval = Session["ImageID1"].ToString();
Session["ImageID1"] = null;
return retval;
}
Here is the javascript:
// on the aspx front end (chartofthedayadmin.aspx) I have the javascript
// to call the Web method and the javascript failed message:
function UploadComplete1() {
var str = PageMethods.GetImageID1(uploadSuccess1, uploadFailed);
}
function uploadFailed() {
alert('error occurred or some meaningfull error stuff');
}
*// javascript on the user control (upload_chart.ascx) to set the value of the hidden field*
function uploadSuccess1(result) {
document.getElementById('<%= fldImageID.ClientID %>').value = result;
}
note: Make sure your scriptmanager has EnablePageMethods="true".
The better and more simple solution is in code behind:
string script = String.Format("top.document.getElementById('hdnFilename').value='{0}';", safeFilename);
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "hdnFilenameFromCodeBehind", script, true);
In my case, safeFilename is the unique filename, after handling duplicate filename, i.e. sample_5.png in the 5th upload of sample.png.
See http://forums.asp.net/t/1503989.aspx