I'm developing a module for OpenCart 3.x and I'm trying to insert some JavaScript code into website's front via $this->load->view() method but cannot get it to work, as the JS code doesn't appear in the DOM.
Here's an excerpt of my code:
/catalog/controller/extension/module/mymodule.php
class ControllerExtensionModuleMyModule extends Controller {
public function index() {
$this->load->language('extension/module/mymodule');
$this->load->model('checkout/order');
$this->load->model('setting/setting');
$this->load->model('design/layout');
$this->load->model('catalog/category');
$this->load->model('catalog/manufacturer');
$this->load->model('catalog/product');
$this->load->model('catalog/information');
$data['js_output'] = "Some JS output";
return $this->load->view('extension/module/mymodule', $data);
}
}
catalog/view/theme/default/template/extension/module/mymodule.twig
<script type="text/javascript">
console.log('This is working!");
</script>
Am I missing something?
Add an external javascript file via controller like this:
$this->document->addScript('catalog/view/javascript/my-external-script.js');
But if it's a block of javascript code, you don't need to edit controller file, just add it to your view file (twig or tpl):
<script type="text/javascript">
console.log("This is working!");
</script>
Finally you may need to clear caches (vqmod, ocmod, twig etc ...).
EDIT
If you want to prepare your javascript code in the controller, follow this:
controller
$data['js_output'] =
'<script type="text/javascript">
console.log("This is working!");
</script>';
Twig
{{ js_output }}
I have finally fixed the issue. It was a problem with the install() method not correctly inserting and loading the design/layout ($this->model_design_layout->getLayouts()).
If your module needs to insert a layout into the layout_module table, make sure you have the correct layout_id, code(which must be your module name), position (i.e: 'content_bottom') and sort_order(which often times is > 90).
Related
As SystemJs loads modules async you can not bind events into the html file directly. Even when you declare the controls after System.import all functions are undefined at this time.
For example the following is not working:
<script type="text/javascript">
System.import('myModule'); //myModule contains a function called onClick.
</script>
#(Html.Kendo().Button()
.Name("RazorButton")
.Content("RazorButton")
.HtmlAttributes(new { type = "button" })
.Events(ev => ev.Click("onClick")))
<button id="html5Button">Html5 Button</button>
<script type="text/javascript">
$("#html5Button").kendoButton({
click: onClick
});
</script>
In this example onClick is allways undefined.
This is not really a problem with the html5 way as I can init the button into the module. With the MVC wrapper however it is the common way to init the button in here.
Is there a way to use the Kendo MVC wrapper in combination with SystemJs module laoding with no drawbacks?
I did not really found a solution with absolutly no drawback.
However, this solution works for me:
Ceate a methods bindEvents in your Module.
myModule.ts
export class MyModule {
bindEvents = () => {
$("#RazorButton").data("kendoButton").bind("click", this.buttonClick);
}
buttonClick = (e) => {
//do something...
}
}
Create a factory for your Module.
myModuleFactory.ts:
import { MyModule} from "./myModule";
export function Create(): MyModule{
return new MyModule();
}
Import the Factory into the View. Call the Create Methods from the factory and get MyModule as Return value. Then call bindEvents from MyModule.
view.cshtml:
<script type="text/javascript">
System.import('myModuleFactory').then(function (e) {
var vm = e.Create();
vm.bindEvents();
}).catch(console.error.bind(console));
</script>
The drawback in here is, that you need to know the name of the kendo event.
In my play framework app, I have a main.html, which at the very bottom includes this javascript tag:
<script>
$(function() {
// add js here
#{scripts /}
});
</script>
Now I would like to be able to add arbitrary javascript from other templates, which is then collected and added to the function body, so for example in view1.html, I'd like to add the function doCharts() to be called on jQuery's DOMReady:
#{append: 'scripts'}
doCharts();
#{/append}
This should then produce this output:
<script>
$(function() {
// add js here
doCharts();
});
</script>
Is this possible?
Yes this is possible
In your main file, after your script tag put
#{get 'moreScripts' /}
and in your other html files use
#{set 'moreScripts'}
<script type="text/javascript">
// put your script here
</script>
#{/set}
if you want to put another script in the same page you can put a get into the set like this
#{set 'moreScripts'}
#{get 'moreScripts' /}
<script type="text/javascript">
// put your script here
</script>
#{/set}
I'm having quite the problem with Handlebars.JS as it is not replacing {{anything}} with the corresponding variables.
I have the following helper function:
function compileTemplate(name){
return Handlebars.compile($('#'+name+'-template').html());
}
Which I use in the following Backbone view:
Soccer.Teams.Li = compileTemplate('team-li');
Soccer.Router = Backbone.Router.extend({
routes: {
"": "index"
},
index: function(){
Soccer.container.html(compileTemplate('main'));
var teams = new Soccer.Teams.View();
var container = Soccer.container.find('.sub-content');
container.html(teams.render().$el.html());
var teamsList = container.find('#teams-list');
teams.teams.forEach(function(team){
teamsList.append(Soccer.Teams.Li(team.toJSON()));
}, this);
Soccer.page.trigger('pagecreate');
}
});
And #team-li-template is the following:
<script id="team-li-template" type="text/x-handlebars-template">
<li team-id="{{id}}"><a>{{name}}</a></li>
</script>
The correct information is definitely being passed, if I console.log the .toJSON it does contain the correct information, but nothing is replaced, the tags are just turned into nothing.
Any ideas?
Thanks!
Update:
Strangely enough I copied all of my code to a JSFiddle and it worked fine:
http://jsfiddle.net/vcrhh/1/
The actual app is 54.235.201.41 (sorry, wouldn't let me add it as a link).
Also tried just saving the code as a file locally and running it, that works fine too.
User username: mkremer90#gmail.com and password test for both. See anything wrong with the actual app? Why would it work in JSFiddle/local and not in my app?
The Handlebars and Backbone looks fine and the fiddle runs so the problem is with your testing environment. When I look at the page source on your server, I see this:
<script id="team-li-template" type="text/x-handlebars-template">
<li team-id=""><a></a></li>
</script>
Note the conspicuous absence of braces. I'd guess that something server-side is eating your braces. You say that you're using Django so Django's templates are probably causing your problem.
I have built a html page with some internal templates. See url jsfiddle:
http://jsfiddle.net/hoven002/jQTDH/
What is the best method to make the templates external and how?
Regards,
Kenneth
The best method, in my opinion, is to use this plugin: https://github.com/ifandelse/Knockout.js-External-Template-Engine.
It enables a new template engine that will pull templates from external files. It has some configuration options as well to determine where the templates are pulled from.
I've written a function that loads templates, without any dependency but jQuery. You must mark each <script> tags you want to be dynamically loaded with the attribute data-template-src and put there the path of your HTML file. Following is the code and an example.
Warning: since it uses AJAX to load templates, it needs an HTTP server (it won't work locally with file:// protocol)
/main.js
// Loads all the templates defined with the tag data-template-src.
// Returns a promise that fulfills when all the loads are done.
function loadTemplates() {
var templateLoads = [];
$('[data-template-src]').each(function () {
var templateElement = $(this);
var templateUrl = templateElement.attr('data-template-src');
// Load the template into the element and push the promise to do that into the templateLoads array
templateLoads.push(
$.get(templateUrl)
.done(function (data) {
templateElement.html(data);
})
);
});
return $.when.apply($, templateLoads);
}
// When all templates are loaded, apply bindings
loadTemplates().done(function () {
ko.applyBindings({}, document.getElementById("htmlDoc"));
});
/index.html
<html id="htmlDoc">
<body>
<div data-bind="template: { name: 'exampleTemplate' }"></div>
<script type="text/html" id="exampleTemplate" data-template-src="/assets/exampleTemplate.html"></script>
<script src="/jquery.js"></script>
<script src="/knockout.js"></script>
<script src="/main.js"></script>
</body>
</html>
/assets/exampleTemplate.html
<h1>Hello world</h1>
<div data-bind="template: { name: 'exampleSubTemplate' }"></div>
/assets/exampleSubTemplate.html
<h2>How do you do?</h2>
Hi there I'm trying using Jade's blocks and extends for a node.js project, and the ideia is to have something like this:
layout.jade:
head
script
$(document).ready(function() {
block js_doc_ready
//here goes the doc ready
});
index.jade:
block js_doc_ready
alert('hello!');
alert('one more js line code');
alert('end my js doc ready for this view');
This would give me a index.html like this:
...
<head>
<script type="text/javascript">
$(document).ready(function() {
alert('hello!');
alert('one more js line code');
alert('end my js doc ready for this view');
});
</script>
</head>
...
But when I see the result, the 'block js_doc_ready' is not considered a Jade block.
Also, even if it was considered a block, the "alert('hello!);' wouldn't be considered a, but a Jade tag.
This is something that I used to do in django template, but in jade with all this tags, and no liberty to do pure html I still find it a little too strange to make this things.
Jade do not translate what's inside 'style' and 'script' code. Never.
What will work is based on an answer I gave to another question (using a style element but that's basically the same).
!!!
head
title Hello jade
| <script type='text/javascript'>
| $(document).ready(function() {
block js_doc_ready
| });
| </script>
This way : jade will include the HTML 'script' tags and $.ready lines but will also include your block.