Create a Cancel button for Joomla 3.2 custom component - joomla-extensions

I am trying to build a Joomla 3.2 custom component and am having a difficult time getting the cancel button (admin section) to work. I've added the button, but when I click it I get the error:
0 Invalid controller: name='helloworld', format=''
This is for the component 'helloworld' and the view 'goodbye'. Could someone look at my files and tell me how to get the 'cancel' button to work? I just want it to close the current page and return to the default component page.
Thanks for any help.
/administrator/views/goodbye/view.html.php
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla view library
jimport('joomla.application.component.view');
/**
* HTML View class for the HelloWorld Component
*/
class HelloWorldViewGoodbye extends JViewLegacy
{
// Overwriting JView display method
function display($tpl = null)
{
$this->addToolbar();
// Display the view
parent::display($tpl);
}
protected function addToolbar()
{
JToolbarHelper::title('Race Results','tbar');
JToolbarHelper::cancel('helloworld.cancel', 'JTOOLBAR_CLOSE');
}
}
/administrator/views/goodbye/tmpl/default.php
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
?>
<h1>Cancel Race Results</h1>
<script type="text/javascript">
Joomla.submitbutton = function(task)
{
if (task == 'helloworld.cancel')
{
Joomla.submitform(task, document.getElementById('helloworld-form'));
}
}
</script>
<form id="helloworld-form" name="adminForm" method="post" action="<?php echo JRoute::_('index.php?option=com_helloworld&view=goodbye'); ?>">
<input type="hidden" name="option" value="com_helloworld" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="view" value="goodbye" />
<?php echo JHtml::_('form.token'); ?>
</form>
/administrator/controllers/goodbye.php
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla modelitem library
jimport('joomla.application.component.controller');
/**
* HelloWorld Model
*/
class HelloWorldControllerGoodbye extends JControllerLegacy
{
public function edit() {
}
public function add() {
}
public function remove() {
}
public function save() {
}
public function apply() {
}
}
/administrator/models/goodbye.php
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla modelitem library
jimport('joomla.application.component.model');
/**
* HelloWorld Model
*/
class HelloWorldModelGoodbye extends JModelLegacy
{
}

depending on action you would like to achieve
Add to controller
public function cancel($key = null) {
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view=name_of the_view' , false));
return true;
}
In view.html add condition to your button
if (condition when to use button)
{
JToolbarHelper::cancel('your_controller_name.cancel');
}
else
{
JToolbarHelper::cancel('your_controller_name', 'JTOOLBAR_CLOSE');
}

Change HelloWorldViewGoodbye to GoodbyeViewGoodbye and same other.

Related

How do I open a browser window/tab from blazor webassembly project behind code:

I'm converting a UWP app to Blazor WebAssembly with ASP.NET Core hosted.
I have my markup code in Index.razor and behind code in Index.razor.cs.
In the UWP project I opened a browser window from an onclick function like this:
var success = Windows.System.Launcher.LaunchUriAsync(targetPage);
What can I use in my Blazor project onclick event, that won't lead to "unhandled error has occurred"?
You can open a tab by making use of the 'window.open' function:
#inject IJSRuntime JSRuntime;
....
await JSRuntime.InvokeAsync<string>("open", $"https://www.mysite/mypage", "_blank");
if the page is internal to your website you can use the base uri:
#inject NavigationManager Navigation
#inject IJSRuntime JSRuntime;
...
await JSRuntime.InvokeAsync<string>("open", $"{Navigation.BaseUri}/mypage", "_blank");
You case use below way
razor file
JSRuntime.InvokeVoidAsync("OpenWindow");
html file
<script>
function OpenWindow() {
window.open('https://www.google.com', 'Test', 'width=800,height=860,scrollbars=no,toolbar=no,location=no');
return false
}
</script>
These are great answers and I took it one step further to make a re-usable component. My app uses anchors and link buttons so I have a quick-and-dirty switch for each.
ExternalLink.razor
#inject IJSRuntime JSRuntime
#if (Type == "link")
{
#(Text ?? Url)
}
else if (Type == "button")
{
<button type="button" class="btn btn-link" #onclick="OpenWindow">#(Text ?? Url)</button>
}
#code {
[Parameter]
public string Url { get; set; }
[Parameter]
public string Text { get; set; }
[Parameter]
public string Type { get; set; } = "link";
private async Task OpenWindow()
{
await JSRuntime.InvokeAsync<string>("open", Url, "_blank");
}
}
Usage
<ExternalLink Url="https://www.ourwebsite.com/" Text="Visit Us!" />
<ExternalLink Url="https://stackoverflow.com/" />
<ExternalLink Url="https://duckduckgo.com/" Type="button" />
Why not just use the build in NavigationManager?
Navigation.NavigateTo(a_url, true);
The trick is to use the force parameter.
Happy coding.

Posting an array of string

I am trying to post a string array to the post action in an Razor Pages project. For this, I thought about using a hidden <select> tag. The user would enter text into a text box, press a button and I would then add a new option to the <select> then post the whole thing with a submit button. However, after everything is posted, the array property of my model is empty.
Does anyone know if there is a better way of doing this or what I am doing wrong?
Razor:
<form method="post">
<input id="string-value" />
<input type="button" id="add-item" value="Add item" />
<select asp-items="#Model.Model.ArrayOfStrings" id="hidden-select"></select>
<table id="table-items">
</table>
<input type="submit" value="Submit" />
</form>
public class ArrayModel
{
public List<SelectListItem> ArrayOfStrings { get; set; } = new List<SelectListItem>();
}
public class IndexModel : PageModel
{
[BindProperty]
public ArrayModel Model { get; set; }
public void OnGet()
{
Model = new ArrayModel();
}
public void OnPost()
{
System.Diagnostics.Debugger.Break();
}
}
JS:
$('#add-item').on('click', function () {
debugger;
var value = $('#string-value').val();
$('#hidden-select').append(new Option(value, value));
$('#table-item tr:last').after('<tr><td>' + value + '</td></tr>')
});
Repository can be found here.
The options of the select will not be posted so this will not work.
The easiest way to do this is append the results to a hidden input with a separator char, then do a string split on the server side.
Another, maybee more elegant way, would be to add hidden inputs with the same name. Each input with it's own value. You should then be able to get this as a List or Array on the server.
Razor:
<input value="#String.Join(",", Model.Model.ArrayOfStrings)" id="tags"></select>
JS
$('#tags').val($('#tags').val() + ',' + value);
Controller
public void OnPost(string tags)
{
var tagsArray = tags.split(',');
}

lit-element - How to call an event from a slot button?

element
import { LitElement, html } from 'lit-element';
class Component extends LitElement {
render () {
return html`
<slot name="activator">
<button #click="${this.openDialog}">Default Button</button>
</slot>
<custom-dialog></custom-dialog>
`;
}
openDialog () {
// code to open dialog
}
}
customElements.define('custom-dialog', Component);
index.html
<head>
<script type="module" src="src/custom-dialog.js"></script>
</head>
<body>
<custom-dialog>
<button slot="activator">Outside Button</button>
</custom-dialog>
</body>
Given the custom component above and my implementation on a simple html page. You'll notice that I'm using a slot button.
How do I call the openDialog() method using the slot button?
I checked docs for events but I found nothing relevant to this.
Thanks in advance.
You need a click event listener on the slot or some ancestor of the slot:
Try moving the #click binding to the slot element itself. click events bubble, so this will handle both the default slot content button and the slotted button from the light DOM. This might not work in ShadyDOM, so you may want to put the event listened on a wrapper element around the slot.
import { LitElement, html } from 'lit-element';
class Component extends LitElement {
render () {
return html`
<slot name="activator" #click="${this.openDialog}">
<button>Default Button</button>
</slot>
<custom-dialog></custom-dialog>
`;
}
openDialog () {
// code to open dialog
}
}
customElements.define('custom-dialog', Component);

how to access data of one view on another view in asp.net mvc5

I have created a controller with following code.
**I am not using any model in this example.
public ActionResult PersonalDetails()
{
return View();
}
[HttpPost]
public ActionResult Thanks(FormCollection formcol)
{
return View();
}
also a view is added for PersonalDetails action with following markup.
#{
ViewBag.Title = "PersonalDetails";
}
<h2>PersonalDetails</h2>
#{
ViewBag.Title = "PersonalDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>PersonalDetails</h2>
#using (Html.BeginForm("Thanks", "DemoForms", FormMethod.Post))
{
#Html.ValidationSummary()
<p>
Your Name : #Html.TextBox("FirstName")
</p>
<br />
<p>
Your Name : #Html.TextBox("LastName")
</p>
<p> Your Phone : #Html.TextBox("Phone")</p>
<p> #Html.RadioButton("Gender", "Male", true) Male</p>
<br />
<p>#Html.RadioButton("Gender", "Female", false) Female </p>
<p> #Html.CheckBox("Reading", true) Reading</p><br />
<p> #Html.CheckBox("Cooking", false) Cooking</p><br />
<p> #Html.CheckBox("Cooking", false) Painting</p><br />
<p>
Would you like to participate in Survey?
#Html.DropDownList("ddlResponse", new[]
{
new SelectListItem() {Text="Yes", Value="Yes"},
new SelectListItem() {Text="No", Value="No"}
}, "Choose an Option")
</p>
<input type="submit" value="Submit Invite" />
}
when user enter the information in above view and click on submit button, it will redirect to Thanks action.
I want to create a Thanks view that will show this information.
Please let me know how I can show/ access the information on Thanks view.
Thank you in advance.
A typical way to do this is to simply send the data to the new view on the server. There are a lot of different patterns. For model binding, do something like this:
[HttpPost]
public ActionResult Thanks(FormCollection formcol)
{
ThanksViewModel model=new ThanksViewModel();
//add the data to the model
return View(model); //return the model with the view
}
If you're not using the model-binding functionality in your view pages, you can always pass data using the ViewBag:
[HttpPost]
public ActionResult Thanks(FormCollection formcol)
{
ViewBag.ThanksData="data"; //add data as properties of ViewBag
return View();
}
The ViewBag is just a built-in dynamic type that you can store any data on. You can then render this data in the view using the standard razor syntax. Eg in the razor page:
#{
ViewBag.Title = "PersonalDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>PersonalDetails</h2>
<p>#ViewBag.ThanksData</p>
We can use TempData also
In Controller:
[HttpPost]
public ActionResult Thanks()
{
TempData["Thanksdata"] = "data";
return View();
}
In View:
<h2>#TempData["Thanksdata"]</h2>
we can use Viewdata also
in controller:
ViewData["Thanksdata"] = "data";
View:
<h2>#ViewData["Thanksdata"]</h2>
Difference between ViewData ViewBag TempData
http://www.c-sharpcorner.com/Blogs/14947/difference-between-viewdata-viewbag-and-tempdata.aspx

creating simple reusable component in Apache Tapestry5

I am starting an adventure with Apache Tapestry5. I am trying to make simple component (for tests), consisting of pair of Textfields. Component is named "TestComp". I have following elements:
testComp.tml
<t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<p>
<input t:type="TextField" t:id="testOne" t:value="testOne.input"/><br/>
<input t:type="TextField" t:id="testTwo" t:value="testTwo.input"/><br/>
</p>
</t:container>
TestComp.java
public class TestComp {
private DataContainer testOne;
private DataContainer testTwo;
#SetupRender
public void setup(){
testOne = new DataContainer();
testTwo = new DataContainer();
}
public String getContentOfTestOne() {
return testOne.getInput();
}
public String getContentOfTestTwo() {
return testTwo.getInput();
}
public DataContainer getTestOne() {
return testOne;
}
public void setTestOne(DataContainer testOne) {
this.testOne = testOne;
}
public DataContainer getTestTwo() {
return testTwo;
}
public void setTestTwo(DataContainer testTwo) {
this.testTwo = testTwo;
}
}
And then I am trying to use it in other place, for example in index.tml:
<form t:type="form" t:id="out">
<t:testComp />
<br/><input type="submit" value="Component"/>
</form>
According to dozens of materials and examples I've found (to be honest non of it refereed to case similar to mine) such implementation should result of showing testComp element in the form, but unfotrunately there is nothing rendered above the button (though tapestry is not crashing). What am I missing? And will I be able to put in Index.java property of TestComp type and bind it with my
<t:testComp />
in Index.tml by id (or it requires something more to implement in my custom component?)
Did you provide the full index.tml file? If so, you are missing the tapestry namespace as well as a correctly setup html document. Try the following:
Index.tml
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<head>
<title>My page</title>
</head>
<body>
<form t:type="form" t:id="out">
<div t:id="testComp" />
<br/><input type="submit" value="Component"/>
</form>
</body>
</html>
In your Index.java you can use this to access your component.
#component(id="testComp")
private TestComp testComp;
If this does not work there is probably something wrong in your configuration or setup and you might just be looking at a static tml file not handled by tapestry at all. In this case follow the step-by-step guide on the Getting Started page.

Resources