I have a internal team website build using python django and angularJS. The website works fine when there is low data/ content on it.
When the website gets scrolled and more data is loaded. It becomes slow.
The major problem occurs when we try to open any modal or try to write text in the textarea. The text lags while writing and modal open very slowly.
I have used nested ng-repeat there are 5 nested ng-repeat.
<div ng-repeat="x in xyz">
<div ng-repeat="y in xyz">
</div>
<div ng-repeat="img in xyz">
</div>
<div ng-repeat="y in xyz">
<div ng-repeat="z in xyz">
</div>
</div>
</div>
Above is the example of the structure being used in the website.
The above snippet repeat itself around 100 times thorughout the page.
These are having images, forms, text, input , user tagging like facebook.
ngCacheBuster,ui.bootstrap, ngTagsInput, ui.mention,monospaced.elastic these are the external library being used in the website.
the website is built using bootstrap.
Is there a specific reason why the website becomes heavy.
each size of the image is around 100kb on an average.
really? the page loads slow when there is alot of data? :D
anyway the most simple method to speed-up heavy data apps is to conditionally load and render parts of it, for example:
<div ng-repeat="x in bla" ng-click="showL1 = true">
<div ng-repeat="y in boo" ng-if="showL1 === true">
//more...
</div>
</div>
on the other part is double check your architecture, since there is a very limited amount of data a person can take from a page and therefor start thinking about tabs and paging
Maybe u need use some function in your controller that will load some part of all data for user.
For example:
app.constant('range' , 10);
app.controller('example', ['$scope', function($scope) {
$scope.loadRangeData = function(range) {
//your way of loading data with using range
}
}
]);
and after u can use ng-repeat as
<div ng-repeat="x in loadRangeData">
but best way it's finding answer in your django maybe
Related
I am listing books using ng-repeat and the blocks have 4 includes inside the ng-repeat which is loading the includes for all the iterations is there any way to load include (ng-include) only once?
The block of code here
index.html
<div ng-repeat="book in books">
<div ng-include="'partial/book'"><div>
</div>
partial/book.html
<div>
<div ng-include="'partial/book/images'"></div>
<div ng-include="'partial/book/isbn-and-info'"></div>
<div ng-include="'partial/book/author'"></div>
<div ng-include="'partial/book/other-books'"></div>
</div>
I came to know the page is taking too long to show the results. So I used the below method to check the partial loads
$scope.$on('$includeContentLoaded', function (event, templateName) {
console.log('content loaded from partials',new Date(),templateName);
});
and got to know that the partials, images, isbn-and-info, author, and other-books are loading all the time (iteration). Is there any way to load all the 4 partials only once to partial/book and use it all the way?
I'm working with a third-party code and I'm quite limited in terms of filtering a list of elements.
Each of these elements has this structure:
<div class="item-preview">
<div class="item-info">
<div class="tag">
<svg class="tag-public"></svg>
</div>
</div>
</div>
The only thing that changes is the svg class, so it's whether tag-public or tag-private. Depending on the user type that's checking the content, I'd like to hide it when it's tag-private. I've tried this:
$('.tag-private').closest('.item-preview').hide();
And this:
$('.tag-private').parents('.item-preview').hide();
But any of them works. The code uses React and the items are brought by JSON/AJAX, so I guess the problem is related to trying to modify the page once is loaded...
Any thoughts on how to make my JS "override" the original code? Thanks a ton.
I have made a widget in Odoo 9 for cutting product description in website view. Added widget="short_desc" to product form view and website product view. I mean something like that:
<span t-field="product.description"/> <!-- full description -->
<span t-field="product.description" t-field-options='{"widget": "short_desc"}'/> <!-- short description -->
<span t-field="product.description" widget="short_desc"/> <!-- also tried this syntax -->
I found helpful this answer: Odoo 9. How to override form widgets?, but it works only in product form and doesn't on website.
So, I have a widgets.js:
odoo.define('wsup.widgets', function (require) {
'use strict';
var core = require('web.core');
var FieldChar = core.form_widget_registry.get('char');
var ShortDescriptionView = FieldChar.extend({
render_value: function() {
console.log('hey, im working!');
this.$el.html('<span>Ok, widget really works</span>');
},
});
core.form_widget_registry.add('short_desc', ShortDescriptionView);
});
When I go to Sales -> Products and open any product, I can see "Ok, widget really works" instead of its description, but when I go to /shop page — product description still has no changes and nothing in JS console.
Here is part of my website product XML view (it works good at all, except short description part):
<div class="product-preview oe_website_sale">
<div class="product-preview__image">
<a t-attf-href="/shop/product/{{ item.id }}">
<span itemprop="image" t-field="item.image" t-field-options='{"widget": "image"}' t-att-alt="item.name"/>
</a>
</div>
<div class="product-preview__info text-center">
<div class="product-preview__info__title">
<h2><a t-attf-href="/shop/product/{{ item.id }}"><span t-field="item.name"/></a></h2>
</div>
<div class="product-preview__info__description">
<p><span t-field="item.description" t-field-options='{"widget": "short_desc"}'/></p>
</div>
</div>
</div>
Why it doesn't work on /shop page? What I forgot to do? Thank you.
As I understand your comment your requirement was to show small amount of description rather than showing a huge description. So, I think this requirement can be easily achieved without create a widget.
Suppose, you have this content as description:
Two is better than one.
Unlike many small headphones, each earpiece of the Apple In-Ear Headphones contains two separate high-performance drivers — a woofer to handle bass and mid-range sounds and a tweeter for high-frequency audio. These dedicated drivers help ensure accurate, detailed sound across the entire sonic spectrum. The result: you’re immersed in the music and hear details you never knew existed. Even when listening to an old favorite, you may feel like you’re hearing it for the first time.
And from this much description if you want to show small amount of description or number of words than you can simple use the below code.
<span t-if="product.website_description and len(product.website_description) > 500">
<t t-set="description" t-value="product.website_description[:500] and product.website_description[:500].replace('+', '\n')+'...'"/>
<p class="text-muted ">
<t t-raw="description"/>
</p>
</span>
In this above code, [:500] will be the number of words to be used.
Output will be:
Two is better than one.
Unlike many small headphones, each earpiece of the Apple In-Ear Headphones contains two separate high-performance drivers — a woofer to han...
Hope, this code will help you.
Thanks.
I'm working on an Angular app that makes a call to a data service and then repeats the results in the view. Each result has a unique, external link. I've found that, in Safari, when you click the link and then navigate backwards with the browser button, you see only the bracketed Angular template text. So,
<div ng-repeat="i in items">
<div>{{i.name}}</div>
<div>{{i.location}}</div>
<div>{{i.link_name}}</div>
</div>
yields
{{i.name}}
{{i.location}}
{{i.link_name}}
with the anchor being just an empty link. This phenomenon does not appear in Chrome. The app is being served by Rails.
That is basically uncompiled html by angular shown on HTML. In that case I'd prefer you to use ng-bind directive to html on page.
<div ng-repeat="i in items">
<div ng-bind="i.name"></div>
<div ng-bind="i.location">{{i.}}</div>
<div><a ng-href="{{i.link}}" ng-bind="i.link_name"></a></div>
</div>
I have an AngularJS application that has a list of contents on the menu. When the user clicks on an item on the menu, the content loads on the main view. There are multiple content types:
When "1" is clicked, a video is loaded. When "2" is clicked, a PDF document is loaded, and so on. Content types may repeat and be complex.
Now, I am setting $scope.content when an item is clicked and, depending on its contentType, I'm calling a different directive:
<div class="content" ng-switch on="content.contentType">
<div ng-switch-when="video">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-switch-when="pdf">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-switch-when="...">
<...-directive content="content"></...-directive>
</div>
</div>
Now I have two problems:
When the page is loaded, all the directive templates are automatically loaded. Even if I don't have a PDF in the menu, the pdf template and scripts will be loaded.
Searching for it, I learned that directives should be tiny, not entire modules of my app.
How do I rewrite the switch above so I can comply with the best practices and load the templates and scripts only when needed?
This is exactly what UI-Router is for: Angular UI Router
Decent tutorial on scotch.io
An easier drop-in replacement for your code may be to simply use ng-if. Ng-if won't instantiate the directive until it's called. Just make sure that your directives aren't transcluding the outer div- if that's the case, shut transclusion off, or add another div to wrap them.
<div class="content">
<div ng-if="content.contentType=='video'">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-if="content.contentType=='pdf'">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-if="content.contentType=='...'">
<...-directive content="content"></...-directive>
</div>
</div>