Force template refresh ember.js - javascript

I'm using I18n localization package to take care of the switching language part of my app. It uses a global variable to set the language wanted and a json file to store the translations.
As the switching of a language is just a change in a global variable ember doesn't detect it and doesn't render the templates automatically. I forced it via an action in the application controller :
Extranet.ApplicationController = Ember.ObjectController.extend(
{
actions:
{
localToFr: function()
{
this.localisation('fr'); // this changes the global variable
this.get('target.router').refresh(); // this is what refresh the template
},
localToEn: function()
{
this.localisation('en');
this.get('target.router').refresh();
}
},
localisation: function(lg)
{
I18n.locale = lg;
}
})
I have two problems with that solution :
1) The application template isn't rerendered via my
this.get('target.router').refresh();
2) And my other problem, it doesn't work on templates which don't request a server access ( e.g. : the nest of routes 'authSession' )
Extranet.Router.map(function()
{
this.resource(
'parkings', {path:'/'}, function ()
{
this.route('parking', {path:'/parking/:parking_id'});
this.route('historique', {path:'/parking/:parking_id/historique'});
this.route('sessAct', {path:'/parking/:parking_id/sessAct'});
this.route('rapport', {path:'/parking/:parking_id/rapport'});
}
);
this.resource(
'authSession', function ()
{
this.route('login');
this.route('logout');
}
);
}
);

I was having a similar issue. I just went with View.rerender() on the main view, which was a form in my case.

Related

Using jQuery to manipulate xml odoo elements

I've made some new modules in my Odoo and now when each form is loading I need to manipulate the created XML elements according to its required model and my arbitrary changes or refer to some specific function for its data validation (I know there are other ways for data validation but I'm curious if it's possible to be done with jquery functions).
I've tried to add an HTML file in the view folder and write a simple script, to begin with, but I'm not sure if it's the right place or even the right piece of code.
<script>
$(document).ready(function()
{
$("input").keyup(function(event){
console.log('t');
});
});
</script>
I would be glad if anyone could offer some useful answers to my question.
You can customize an existing form view using the js_class attribute, its value will be the name of an extended form view.
To bind a new event to an input, you can customize the form controller and extend the events mapping.
Example:
1) Extend the form view:
odoo.define("MODULE_NAME.custom_form", function (require) {
"use strict";
var FormController = require('web.FormController');
var FormView = require('web.FormView');
var viewRegistry = require('web.view_registry');
var CustomController = FormController.extend({
events: _.extend({}, FormController.prototype.events, {
'keyup input': '_onInputKeyup',
}),
_onInputKeyup(ev) {
console.log('t');
},
});
var CustomFormView = FormView.extend({
config: _.extend({}, FormView.prototype.config, {
Controller: CustomController,
}),
});
viewRegistry.add('custom_form', CustomFormView);
return {
CustomController: CustomController,
CustomFormView: CustomFormView,
};
});
2) Add it to the assets entry in the manifest file
'assets': {
'web.assets_backend': [
'MODULE_NAME/static/src/js/custom_form_view.js'
],
},
3) Set the js_class attribute on the form view tag
<form js_class="custom_form">
For back-office javascript, consider using the "Odoo built-in js library":
In your custom module "my_custom_module":
Create a new file /my_custom_module/static/src/js/my_customization.js:
odoo.define('my_custom_module.switch_to_gantt', function(require) {
"use strict";
var core = require('web.core');
var _t = core._t;
var AbstractController = require('web.AbstractController');
AbstractController.include({
/**
* Original : Intercepts the 'switch_view' event to add the controllerID into the data, and lets the event bubble up.
* Included : On switching from Kanban to Gantt view : Remove all the GroupBy Filters because it caused Error
*/
_onSwitchView: function (ev) {
console.log(ev.data.view_type);
//debugger;
/* only on the specific view : gantt: */
if(ev.data.view_type == 'gantt')
{
/* only on the specific model : event.event: */
if(ev.target.modelName == 'event.event')
$('.o_searchview .o_facet_remove').click();
}
this._super.apply(this, arguments);
},
});
});
And declare this asset in the __manifest__.py file:
'assets': {'web.assets_qweb': ['/my_custom_module/static/src/js/my_customization.js']}
if you want to use jquery or any js library you need to put them in this file under this path /your_app/static/src/js/test.js
and the file should be like this :
$(document).ready(function()
{
$("input").keyup(function(event){
console.log('t');
});
});
and you need to add the assets for this work like that :
'assets': {'web.assets_qweb': ['/your_app/static/src/js/test.js']} #path of the file
this for jquery not for building js model in odoo

How to prevent name mangling of javascript functions in django-pipeline

I am using django version 1.82 with django-pipeline. I call a particular javascript function from html by name.
<form class="navbar-form navbar-right vcenter"
action="javascript:search();" role="search" id='searchform'>
Unfortunately in the compressed js file, the name of the function is changed and hence the frontend functionality is not workig. How do I maintain the same name for that function or how do I change the reference to the js function in html?
I have installed yuglify and the settings I use is
PIPELINE_CSS = {
'allstyles': {
'source_filenames': (
'css/application.css',
'feedback/css/feedback-form.css',
),
'output_filename': 'css/nifty.css',
'extra_context': {
'media': 'screen,projection',
},
},
}
PIPELINE_JS = {
'actions': {
'source_filenames': (
'js/nifty.js',
'feedback/js/feedback-form.js',
),
'output_filename': 'js/nifty.js',
}
}
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor'
PIPELINE_DISABLE_WRAPPER = True
PIPELINE_ENABLED=True
Are you sure that search() is a global function? To make sure you can assign it to the window variable:
window.search = function() {
...
}
I'd do it the other way around.
<form ... action="/nojs.html" ... id='searchform'>
and then intercept the submit event on the form.
(function(){
var sf = document.getElementById('searchform');
sf.addEventListener('submit', function(ev){
ev.preventDefault();
// do here whatever "search()" needs to do
});
})();
That way you don't need to add anything into the window namespace, are independent of minified function names, and a browser with disabled JS gets a readable error page.

ReactJS - What is the standard method of initializing jquery plugin in a react class?

I am using this plugin - bootstrap-dropselect
I have written initDropSelect function to initialize this plugin but I am not sure where to call this function as I would like to append some html to the DOM as soon as route is loaded. I am getting data from two different ajax calls. That data has to be compared and manipulated to append that html to the DOM(Code below 'Append to DOM' comment).
let UserPanel = React.createClass({
mixins: [LinkedStateMixin],
getStateFromStores: function() {
var users = UserStore.getAll();
// Some more code
return {
users: users
// Other properties
};
}
componentDidMount: function() {
UserStore.addChangeListener(this._onChange);
},
_onChange: function() {
this.setState(this.getStateFromStores());
},
initDropSelect: function() {
var _self = this;
var dropSelect = $('#dropselect-demo1').dropselect({
filter: {
show: true,
placeholder: 'Search for an item'
},
multiselect: true,
onselect: function(e, item) {
},
onunselect: function(e, item) {
},
onclear: function(e) {
}
});
// Append to DOM
if(this.state.tagsList.length > 0) {
if(this.state.newLoan.data.tags.length > 0) {
// Getting data from two different resources
}
}
}
});
Please help me in deciding where to call initDropSelect to manipulate data from multiple async requests and append that data to DOM.
P.S. I am using react router so there are two scenarios. First I may come to this route from other route or I can straightaway reload the current page.
Thanks in advance.
One way is for your render method to return something like a <div /> that you will then use to mount the jQuery component into. Once mounted, this will point to the DOM element that you would normally pass to jQuery.
Since jQuery will be handling the rendering, you then want to always return false from shouldComponentUpdate(). This will prevent React from thrashing your jQuery component.
You can then use componentDidMount() to initialize your jQuery component and componentWillReceiveProps() to update/re-render it when new data is passed in.

How to Change body background for different pages in ember

I am developing ember app and I would like to have white background for signup page and login page and the rest of the pages should have grey background.
At the moment I am changing colours of body tag in controller (application.js file)
import Ember from 'ember';
export default Ember.Controller.extend({
isVerified:false,
bgColour: function(){
if(['users.login','users.signup'].indexOf(this.get('currentPath')) != -1){
return 'white';
}
else{
return 'bg-grey';
}
}.property('currentPath'),
});
Any advices how to make this better/cleaner way?
The answer from Kit is pretty common, we do the same for our app. But you can simplify it a lot by avoiding generating the classname if you really only need it for a background change:
export default Ember.Route.extend({
activate () {
Ember.$('body').addClass('bg-white');
},
deactivate () {
Ember.$('body').removeClass('bg-white');
}
});
We have to deal with a lot of arbitrary requests from our clients where the easiest way is simply to target a specific page, so we add the route name to the body.
Ember.Route.reopen({
activate: function() {
var cssClass = this.toCssClass();
// you probably don't need the application class
// to be added to the body
if (cssClass != 'application') {
Ember.$('body').addClass(cssClass);
}
},
deactivate: function() {
Ember.$('body').removeClass(this.toCssClass());
},
toCssClass: function() {
return this.routeName.replace(/\./g, '-').dasherize();
}
});
That said it's a big dirty, you could create a ThemeMixin and set it on the routes. It's a simpler version of this: https://github.com/ronco/ember-cli-meta-tags

Pretty routing with total.js (like 'base_url/#username')

I'm new to node.js, have been using Ruby and RoR.
I'd like to show a view for user view with a pretty routing.
In Rails, I can handle with code like this:
get '#:username' => 'users#show'
So I tried in Total.js as same, but error appeaerd with 404: Not found:
exports.install = function() {
F.route('/#{username}', view_user);
}
How can I get my user view with localhost:8000/#my_name in total.js?
You must remove # from the route:
exports.install = function() {
F.route('/{username}/', view_user);
};
function view_user(username) {
if (!username.startsWith('#')) {
this.throw404();
else
this.plain(username);
});
Thanks.

Categories