How to change the Title text for a "Resource" component on right panel - admin-on-rest

This link explains the way to change the Text on Menu - https://github.com/marmelab/admin-on-rest/blob/master/docs/Resource.md#options
But I would like to know how to change the Text which is rendered on right side panel i.e. when one clicks on the drawer menu. I see that if my code is like this :
<Resource name="v2/posts" options={{ label: 'Posts' }} list={PostList} />
then the Title is rendered as V2/Posts List. How do I give a custom title ?

You have to provide the title prop to your PostList component, e.g.
<PostList {...props} title={'Your title'} >
...

Or you could make your custom title:
<PostList title={<PostTitle />} {...props} >
where PostTitle is:
const PostTitle = ({ record }) => {
return <span>My title</span>;
};

Related

populate cards and modals via same json file using react(-bootstrap)?

The data from workData fills <Card></Card> correctly.
The <Modal></Modal> only fills with the last entry of workData (e.g. Test4, Modal4, test text 4...)
my goal is to generate cards and respective modals (for each card) using the data from the json, in the same file.
why is the modal only being filled by the last properties in the json? how do i get it to populate with the entire array? if possible please explain why this does not work the way it is.
if it's not obvious im super new, i am, any responses would be super appreciated. ty
cards good
after clicking "Read1" bad, should say Test1, test text 1
in App.js: import { Works } from "./Works";
in Works.js: import { workData } from "./data";
also in Work.js:
export const Works = () => {
const [show, setShow] = React.useState(false);
const onClick = () => setShow(true);
return (
<>
<div className="work-container">
<Row xs={1} md={2} lg={4} className="g-4">
{workData.map((data, key) => {
return (
<div key={key}>
<Col>
<Card>
<Card.Img variant="top" src={data.projectImage} />
<Card.Body>
<Card.Title>{data.projectTitle}</Card.Title>
<Card.Text>with {data.projectTeam}</Card.Text>
<Button variant="link" onClick={onClick}>
{data.readMore}
</Button>
</Card.Body>
<Card.Footer>{data.tags}</Card.Footer>
</Card>
</Col>
<Modal
show={show}
onHide={() => setShow(false)}
dialogClassName="modal-95w"
>
<Modal.Header closeButton>
<Modal.Title>{data.projectTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Image src={data.projectImage}></Image>
<p>
{data.modalText}
</p>
<Image src={data.modalImage}></Image>
</Modal.Body>
</Modal>
</div>
);
})}
</Row>
</div>
</>
);
}
in data.js:
export const workData = [
{
projectTitle: "Test1",
modalTitle: "Modal1",
modalText: "test text 1",
modalImage: "image",
readMore: "Read1",
projectImage: "image",
projectTeam: "Test1",
year: "2022",
link1: "link",
link2: "link2",
tags: [
"#tag1 ",
"#tag2 "
]
},
...
The data from workData fills <Card></Card> correctly.
The <Modal></Modal> only fills with the last entry of workData (e.g. Test4, Modal4, test text 4...)
my goal is to generate cards and respective modals (for each card) using the data from the json, in the same file.
why is the modal only being filled by the last properties in the json? how do i get it to populate with the entire array? if possible please explain why this does not work the way it is.
cards good
after clicking "Read1" bad, should say Test1, test text 1
You iterate over workData for Cards and Modals, but you use only one single state for everything. What you need to do, is to also create a state for every Modal. Usually you create an array with unique id as key and boolean value. I assumed projectTitle is unique:
{
Test1: false,
Test2: false,
Test3: false
}
Because you don't know the length of your data, you just iterate over the array, as you have done for Cards und Modals:
const initialShowState = Object.fromEntries(
workData.map((data) => [data.projectTitle, false])
);
const [show, setShow] = React.useState(initialShowState);
Then you need to create a generic callback function, which takes the id of the Card and shows the appropriate Modal. I simplified the logic and created a toggle function:
const toggleShow = (id) =>
setShow((prev) => {
return { ...prev, [id]: !prev[id] };
});
Finally, when you render UI and iterate over workData, you need to apply the callback function to Button onClick and Modal onHide event handlers and set the show property of Modal:
<Button variant="link" onClick={() => toggleShow(data.projectTitle)}>
...
<Modal
show={show[data.projectTitle]}
onHide={() => toggleShow(data.projectTitle)}
dialogClassName="modal-95w"
>
That's it. Here is the working sandbox: https://codesandbox.io/s/hungry-sunset-t865t3
Some general tips:
You don't need the outer Fragment in Works as you only have one upper most element
If you use JSX syntax in your file, your extension should be .jsx and not.js (Works.jsx)
Using index as key in the list is bad practice. Find some unique id in your data

React-Admin How to change the "Dashboard" name in the menu

How can I change the "dashoboard" menu name in the react-admin?
By default it's name is always "Dashboard" even in the Demo
the name is Dashboard. Someone knows a way to change the name or if it is even possible to change?
At the Menu.tsx, don't call it like
<DashboardMenuItem onClick={onMenuClick} sidebarIsOpen={open} />
Instead call it like a normal menu item but pointing to the dashboard component
<MenuItemLink
to={`/`} // by default react-admin renders Dashboard on this route
primaryText="Your Text"
leftIcon={<YourIcon />}
onClick={onMenuClick}
sidebarIsOpen={open}
dense={dense}
/>
Like in that answer is showed that in the MenuItemLink has an atribute called primaryText="Your Text" that you can use in your own
<DashboardMenuItem onClick={onMenuClick} classes={classes} primaryText="Your Text" />
To change the name of the default "Dashboard" name for what you want.
So more detailed answer is:
Override layout
// in src/Admin.js
<Admin
layout={MyLayout}
title="SuperCoolProject"
theme={myTheme}
dataProvider={dataProvider}
authProvider={authProvider}
>
Use custom menu in layout. (it's not sidebar)
// in src/MyLayout.js
import React from "react";
import { Layout } from "react-admin";
import MyMenu from "./MyMenu";
const MyLayout = (props) => <Layout {...props} menu={MyMenu} />;
export default MyLayout;
Change menu so it still renders resources and add custom MenuItemLinks you need (vs. one hardcoded "dashboard")
// in src/Menu.js
import React from "react";
import { useSelector } from "react-redux";
import { useMediaQuery } from "#material-ui/core";
import { MenuItemLink, getResources } from "react-admin";
import DefaultIcon from "#material-ui/icons/ViewList";
import SettingsIcon from "#material-ui/icons/Settings";
import HomeIcon from "#material-ui/icons/Home";
import HelpIcon from "#material-ui/icons/Help";
const Menu = ({ onMenuClick, logout }) => {
const isXSmall = useMediaQuery((theme) => theme.breakpoints.down("xs"));
const open = useSelector((state) => state.admin.ui.sidebarOpen);
const resources = useSelector(getResources);
return (
<div>
<MenuItemLink
to="/home"
primaryText="Home"
leftIcon={<HomeIcon />}
onClick={onMenuClick}
sidebarIsOpen={open}
/>
{resources.map((resource) => (
<MenuItemLink
key={resource.name}
to={`/${resource.name}`}
primaryText={
(resource.options && resource.options.label) || resource.name
}
leftIcon={resource.icon ? <resource.icon /> : <DefaultIcon />}
onClick={onMenuClick}
sidebarIsOpen={open}
/>
))}
<MenuItemLink
to="/custom-route"
primaryText="Settings"
leftIcon={<SettingsIcon />}
onClick={onMenuClick}
sidebarIsOpen={open}
/>
<MenuItemLink
to="/help-center"
primaryText="Help Center"
leftIcon={<HelpIcon />}
onClick={onMenuClick}
sidebarIsOpen={open}
/>
{isXSmall && logout}
</div>
);
};
export default Menu;

Nativescript how to make a if condition in View XML

Is there anyway to do a if condition in the XML file of nativescript? (without angular)
if
<Card:CardView class="cardStyle" margin="10" elevation="40" radius="5">
<Slider value="18" minValue="5" maxValue="30" />
</Card:CardView>
else
<Card:CardView class="cardStyle" margin="10" elevation="40" radius="5">
<Label text="Example" class="h3" margin="10" />
</Card:CardView>
What you could do is use a boolean property (which in its get function has the condition you want) and bind it to the visibility of the CardView.
Looks like you can show/hide from the template file using visibility:
In XML file: ie. 'sample-page.xml'
<Button text="{{ isShowing ? 'Hide Me' : 'Show Me' }}" tap="toggleShowing"/> <!-- Notice missing interpolation in Button tag -->
<Label text="Showing Hidden Element" visibility="{{ isShowing ? 'visible' : 'collapsed' }}"/>
In Page file: ie. 'sample-page.ts'
let model = new ViewModel();
// Event handler for Page 'loaded' event attached in main-page.xml
export function pageLoaded(args: observable.EventData) {
const page = <Page>args.object;
page.bindingContext = model;
}
export function toggleShowing() {
model.set('isShowing', !model.get('isShowing'));
}
In View Model: ie. 'sample-view-model.ts'
isShowing:boolean = false;
The only way I found to do to do this was to use the navigatingTo event of the page:
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
var myLayout = <StackLayout>page.getViewById("myLayout");
if (condition) {
let segmentedBar = new SegmentedBar;
...
myLayout.addChild(segmentedBar);
}
else {
let button: Button = new Button;
...
myLayout.addChild(button);
}
No possibility in the template file :-/
It can be done using ng-container.For example
<ng-container *ngIf="true">Your logic here....</ng-container>

Kendo UI / MVC - Getting a Menu item to open in a Tab page instead of calling Action, using onclick?

I have a Kendo UI menu:
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("About").Action("Index", "Home");
}))
Instead of loading the new page with an Action I want to call a javascript function onclick. How can I do this? Should I use the HtmlAttributes property?
Additionally, I'm using the moonlight theme which has white menu item text for non-actions and orange text for action menu items. For my menu item which will call the javascript function how would I keep this as orange text? By setting a style, or is there another way?
My sample code is on http://www.eeedee.com if I haven't explained myself well enough.
Thanks
You can work with andrewdudek84 answer(That way is really great).
There is two more solution (The hacking way):
Solution 1
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("About").Url("javascript:void(0)")
.HtmlAttributes(new {
#class= "helloWorld"
});
}))
<script>
$('.helloWorld').click(function(){
//put your code here
});
</script>
Solution 2
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("About").Action("Index", "Home")
.HtmlAttributes(new {
#class= "helloWorld"
});
}))
<script>
$('.helloWorld').click(function(e){
e.preventDefault(); // Cancel the default action of your click.
//put your code here
});
</script>
I would suggest something like this:
<ul id="menu">
<li id="menuItem1">Menu Item 1</li>
</ul>
<script type="text/javascript">
$(document).ready(function() {
$("#menu").kendoMenu({
select: menuItemSelect,
theme: "Moonlight"
});
});
function menuItemSelect(e){
alert(e.item.id);
}
</script>
You can also use the "LinkHtmlAttributes" to, um, add attributes to the generated link:
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add()
.Text("About")
.Action("Index", "Home")
.LinkHtmlAttributes(new { id = "myLink", onclick = "return OnMyLinkClick();" });
}))
Slightly off topic, but for anyone looking to call an action method from the menu, but have the target page open in a new tab...
#(Html.Kendo().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add()
.Text("About")
.Action("Index", "Home")
.LinkHtmlAttributes(new { target = "_blank" });
}))

#Html.RadioButtonFor postback

I want to update other controls on the form as soon as I choose a radio button.
How do I get these controls to call the controller as soon as a radio button is clicked. A separate submit (actionLink) button isn't suitable.
My code is
<label for="ApplicationTypes_Single">On your own?</label>
#Html.RadioButtonFor(x => x.ApplicationType, "Single", new { id = "ApplicationTypes_Single" })
<label for="ApplicationTypes_Joint">With someone else?</label>
#Html.RadioButtonFor(x => x.ApplicationType, "Joint", new { id="ApplicationTypes_Joint" })
the control dependant on that selection is
#if(Model.ApplicationType == AffordabilityPage1.ApplicationTypes.Joint)
{
#Html.LabelFor(model => model.SecondAge)
#Html.EditorFor(model => model.SecondAge)
}
Many thanks for any tips given.
You need javascript in order to achieve this. For example if you are using jquery you could subscribe for the change event of those radio buttons and take some action:
$(function() {
$(':radio[id^="ApplicationTypes"]').change(function() {
var value = $(this).val(); // will equal Single or Joint
// Depending on what you are trying to achieve either send an AJAX request
// or force the submission of some form in order to send the new value to the server
});
});

Resources