I need to start working in a directive.
I have 5 different views where the html is exactly the same, so I need to do the directive in order to minimize my HTML.
<div class="list betslip-item">
<div class="item betslip-header"
ng-class="slip.active == '1' ? 'betslip-header-active' : 'betslip-header-inactive'">
<div class="row">
<div class="col slip-name" ng-click="openMoreInfoSlip(slip)">
{{:: slip.teamName}}
</div>
<div class="col-30">
<a class="button-size select-button"
ng-click="swapLineSelection(slip)">
<i class="fa" ng-class="slip.active == '1' ? 'fa-check-circle' : 'fa-plus-circle'"></i>
</a>
<a class="button-size close-button"
ng-click="removeSlip(slip)"><i class="fa fa-times"></i>
</a>
</div>
</div>
</div>
<div class="item item-input" ng-class="(slip.lines.length > 1) ? 'item-select' : ''">
<div class="input-label">
{{:: slip.nss}} - {{::slip.gameDate}}
</div>
<span class="pick-label"
ng-init="currentLine = getCurrentLine(slip)"
ng-if="slip.lines.length < 2">{{:: currentLine.pick}}</span>
<select
ng-if="slip.lines.length > 1"
ng-init="currentLine = getCurrentLine(slip)"
ng-model="currentLine"
ng-options="line as line.pick for line in slip.lines"
ng-change="updateSelectionLine(slip, currentLine.pointsBought)">
</select>
</div>
</div>
That is the HTML I am talking about, I should include css classes and everything, is that possible?
Any help is very welcome.
You don't need to use a custom directive. If all you want to achieve is to be able to reuse some html you can always put it into another template and use it by ng-include:
<ng-include src="'/templates/reusableComponent.html'"></ng-include>
Reusing the same HTML file as 5 different views is possible but you will need to place all the value or data that you require to show on all the 5 pages in one and use javascript or jquery to display according. so instead of doing this creating 5 views would be better, it isn't using up any server processing time, only memory and since it's just 5 views i dont think it would affect it so much also.
i've also included a link of the Angular project that i was working on below, which had aorund 2-3 views so incase you require as to go about that, with ng-route etc.
GitHub link for AngularJS Project
Hope this helps
Related
I have a website that i am trying to personalize and I am trying to use the AnimatedModal.js framework. I have been able to display some content in one modal, but when it comes to make several modal it gets tricky, because there is just one ID. My question i, how can i use the same ID and change the content for other modals(demo03,demo04..etc.), in order to personalize each.
I will put some code in order to understand the problem
I have been reading the documentation but I am still stuck in this problem.
<!-- single work -->
<div class="col-md-4 col-sm-6 ads graphics">
<a id="demo02" href="#animatedModal" class="portfolio_item">
<img src="img/portfolio/03.jpg" alt="image" class="img-responsive" />
<div class="portfolio_item_hover">
<div class="portfolio-border clearfix">
<div class="item_info">
<span>Should open here </span> <em> ads / Graphics </em>
</div>
</div>
</div>
</a>
</div>
<!-- end single work -->
Then I have the demo where it displays the content of the modal, where it has the #animatedmodal ID
<div id="animatedModal" class="popup-modal ">
<!--THIS IS IMPORTANT! to close the modal, the class name has to match the name given on the ID -->
<div id="btn-close-modal" class="close-animatedModal close-popup-modal">
<i class="ion-close-round"></i>
</div>
<div class="clearfix"></div>
<div class="modal-content ">
<div class="container">
<div class="portfolio-padding" >
Hello World
</a>
</div>
</div>
</div>
</div>
this is my Js file where there is just one element assigned to it, to avoid showing the same content into all different classes.
$("#demo02").animatedModal();
I don't think it can be done without hacking the plugin.
As a matter of fact, the script jQuery.animatedModal ALWAYS TARGETS the page element which has id="animatedModal"
You can see the plugin source code here:
https://cdn.jsdelivr.net/npm/animatedmodal#1.0.0/animatedModal.js
...
//Defaults
var settings = $.extend({
modalTarget:'animatedModal',
...
Here is the AnimatedModal reference:
https://joaopereirawd.github.io/animatedModal.js/
At the bottom of the page, I can't see any OPTION regarding how to specify a different target, all options are about styles and animation features.
At this point, I think the only way to allow multiple modals on the same page is to rewrite the plugin, but I'm pretty sure you don't want to choose this way.
I have a page where it loads some values from a spreadsheet, and displays the values on the page. (i.e. so it can handle multiple languages).
Problem
When I put html tags in the spreadsheet, they are not applied.
Example
If I put the following text in an html file and view it, the browser applies the html tags as expected.
<div><a href='http://...'>some <br> value</a></div>
However, when it is applied loaded from the spreadsheet, the <br> tag is not applied and it stays on one line.
<div class="col-xs-12 col-sm-6 pull-right">
<a ui-sref="open.registration.login.resetPassword"
class="bmw-command-link bmw-mt-2 bmw-mb-2">{{ 'gcdm-login.forgotten_password' |
translate }}</a>
</div>
Also, if I update the value in Chromes Developer tools, the value changes in the browser, but html tags are not applied. It is as if the browsers display does not refresh to apply html tags.
Question
Is there a way I can get the html tags read in from the spreadsheet applied?
Is this a timing issue, meaning that the DOM is rendered already and cannot be changed on the fly?
Thanks
It really depends on what version of Angular you use, but for all it resumes to one thing: you have to bind your text as HTML by using either ng-bind-html directive or [innerHTML] property.
AngularJS:
<div class="col-xs-12 col-sm-6 pull-right">
<a ui-sref="open.registration.login.resetPassword"
class="bmw-command-link bmw-mt-2 bmw-mb-2" ng-bind-html="'gcdm-login.forgotten_password' | translate"></a>
</div>
Angular 2-6:
<div class="col-xs-12 col-sm-6 pull-right">
<a ui-sref="open.registration.login.resetPassword"
class="bmw-command-link bmw-mt-2 bmw-mb-2" [innerHTML]="'gcdm-login.forgotten_password' | translate"></a>
</div>
I've also made you an working example here.
its work fine
try this
<div class="col-xs-12 col-sm-6 pull-right">
<a ui-sref="open.registration.login.resetPassword" class="bmw-command-link bmw-mt-2 bmw-mb-2">forgotten<br>password</a>
</div>
I am using two ng repeats but the second one it doesnt display. Let me show you my view :
<div class="post" ng-repeat="user in users | orderBy:'username':false" ng-class-odd="'odd'" ng-class-even="'even'">
<p>{{user.username}}</p>
<small><a ng-click='gotomessages(user.username)' class="btn btn-default">go</a></small>
<small class="pull-right"> Message</small>
<div ng-repeat="message in messages[$index]">
<p>{{message.name}}</p>
</div>
</div>
the $index is the one of the first ng-repeat. Is it possible to use it like i did ? In anyway the second ng repeat doesnt work can you help
Just use $parent.messages[$index] instead of messages[$index] in the second ng-repeat
I am working on Angular Js web app using Laravel 5.2 as API and I have a big issue in the performance specially in the load time of the home page.
I have a request that get 5 sections from database, each section has one or tow items and each item has many comments. I loop through sections then items then comments to render it via nested ng-repeat directive.
I also have a list of filters and another of friends each has its own request and ng-repeat to render it as well.
Is this considerable as huge data to use over Angular JS, How I can enhance the performance of it?
I also have about 20 modules in the dependencies of the main module, Is there a better way to load this module only when I need them?
Notes:
Angular Js version 1.5.1
Angular Js and jQuery loaded via CDN
all other js files are concatenated by GULP.js in one file and it about 66000 lines of code
there is 25 module in the dependencies array of the main module
the time of load is about 25-35 seconds
here is code of my home page section that cause the issue:
<div ng-class="{'col-sm-6':currentUser,'col-sm-9':!currenUser}" fc-loading="getCoupons" class="allCoupons lbm">
<section class="fc-section text-center fc-direction" ng-init='current="all"'>
<button type="button" class='btn btnp btnm0 srm' ng-class='{"btnr":current=="all"}' ng-click='updateCoupons();current="all"' name="button">كل الكوبونات</button>
<button type="button" class='btn btnp btnm0' ng-class='{"btnr":current=="my"}' ng-click='updateCoupons("user");current="my"' name="button">الكوبونات المخصصة لك </button>
</section>
<div ng-repeat='(key,section) in coupon_sections' class="{{key}} fc-programs">
<div class="header">
<div class="clearfix">
<h3 class="pull-left">{{::section.type}}</h3>
<ul ng-init="active = 'newset'" class="pull-right">
<li ng-click="sortCoupons(1,key); active='newset'" ng-class="{active:active == 'newset'}"><span>{{::'sort_by.newest'| translate}}</span></li>
<li ng-click="sortCoupons(2,key); active='oldset'" ng-class="{active:active == 'oldset'}"><span>{{::'sort_by.oldest'| translate}}</span></li>
<li ng-click="sortCoupons(3,key); active='popular'" ng-class="{active:active == 'popular'}"><span>{{::'sort_by.popular'| translate}} </span></li>
</ul>
</div>
</div>
<div class="fc-section">
<p>
{{::section.description}}
</p>
</div>
<div class="lucky_hour centerContainer" ng-if='key =="luckyHour"' ng-init='getTimeRemaining("December 31 2016 23:59:59 GMT+0200")'>
<div class="centerContent">
<ul>
<li class="hh" ng-repeat='hour in hours track by $index'>{{hour}}</li>
<li class="dots">:</li>
<li class="mm" ng-repeat="minute in minutes track by $index">{{minute}}</li>
<li class="dots">:</li>
<li class="ss" ng-repeat="second in seconds track by $index">{{second}}</li>
</ul>
</div>
</div>
<section class="fc-section text-center" ng-if="!section.coupons.length ">
<p class="title">{{::'no_coupons'| translate}}</p>
</section>
<div ng-repeat="coupon in section.coupons">
<fc-coupon ng-init='showCarousel();'></fc-coupon>
</div>
<div class="text-center" ng-if="section.coupons.length ">
<button class="btnloadmore icon-plus-circled btni lbm" ng-click="loadMore(key)">{{::'load_more'| translate}}</button>
</div>
</div>
</div>
here is the fc-coupon template
<div class="fc-coupon lbm" id='{{coupon.coupon_data.slug}}'>
<div class="header bb">
<div class="rippon">
{{::coupon.coupon_data.type}} </div>
<img style="background-image: url('{{::absolute_url+'images/brands/100x100/'+ coupon.brand_data.logo }}')" />
<h3>{{::coupon.brand_data.name}}</h3>
<fc-stars rating="{{::coupon.coupon_data.rate}}" ></fc-stars>
<div class="pull-right">
<!-- <label>{{::'available_for'| translate}}</label> -->
<div class="fc-badge sPadges" ng-repeat="customer in ::coupon.coupon_data.users_type">
<img uib-tooltip="{{:: 'available_for' | translate}} {{::customer.name.name}}" ng-src="{{::absolute_url}}/images/customer-types/50x50/{{customer.image}}">
</div>
</div>
</div>
<div class="sp" ng-if='key !="challenges"'>
<h4>{{::coupon.coupon_data.title}}</h4>
<p hm-read-more
hm-text="{{:: coupon.coupon_data.description }}"
hm-limit="100"
hm-more-text="{{::'read_more'|translate}}"
hm-less-text="{{::'read_less'|translate}}"
hm-dots-class="dots"
hm-link-class="links" class="sbm mtp "></p>
</div>
<div class="sp mtp" ng-if='key =="challenges"'>
<p>
<i class="fc-red icon-award"></i> <span class="fc-purple srm">التحدي </span>
{{::coupon.coupon_data.challenges.name}}
</p>
<p>
<i class="fc-red icon-gift"></i> <span class="fc-purple srm">الجائزة </span>
<span>{{::coupon.coupon_data.type}}</span>
</p>
</div>
<div class="couponImage">
<div class="fc-overlay centerContainer">
<div class="centerContent">
<i ng-if="coupon.coupon_data.in_wallet" class="icon-heart"></i>
<i ng-if="!coupon.coupon_data.in_wallet" ng-click="addToMyCoupons(coupon.coupon_data)" class="icon-heart-empty"></i>
<label>{{::coupon.coupon_data.no_of_users_in_wallet }}</label>
</div>
<div class="couponFooter">
{{::'details'| translate}}
<ul class="socials">
<li><span ng-click="shareCoupon(coupon.coupon_data.slug,'facebook')" spantarget="_blank" class="icon-facebook"></span> </li>
<li><span ng-click="shareCoupon(coupon.coupon_data.slug,'twitter')" class="icon-twitter"></span> </li>
<li><span ng-click="shareCoupon(coupon.coupon_data.slug,'gplus')" class="icon-gplus"></span> </li>
</ul>
</div>
</div>
<img ng-src="{{::absolute_url}}/images/coupons/747x390/{{coupon.coupon_data.image}}"/>
</div>
<div class="couponDetails sp">
<div class="owl-carousel mbm">
<div class="item " ng-repeat="friend in ::coupon.coupon_data.coupon_users">
<div style="background-image: url('{{::absolute_url}}/images/users/75x75/{{friend.picture}}')" class="roundImages mProfilePics"></div>
</div>
</div>
<div ng-init="coupon.coupon_data.isMapCollapsed =true;coupon.coupon_data.isMapOpened=false">
<div class="clearfix bb mbp mtp bt sbm" >
<div class="pull-left srm" ng-click="openBranches(coupon.coupon_data)">
<i class="icon-location"></i>
<label>{{::'branches'| translate}} {{::coupon.coupon_data.no_of_branches}}</label>
</div>
<div class="pull-left">
<i ng-class="{'icon-cancel':coupon.coupon_data.feed_w_estafeed_id ==null,'icon-ok':coupon.coupon_data.feed_w_estafeed_id != null}"></i>
<label>{{::'benefit'| translate}}</label>
</div>
<div class="pull-right">
<i class="icon-share"></i>
<label for="">{{::'share'| translate}} :</label>
<i class="icon-facebook" ng-click='shareCoupon(coupon.coupon_data.slug,"facebook")'></i>
<i class="icon-twitter" ng-click='shareCoupon(coupon.coupon_data.slug,"twitter")'></i>
</div>
</div>
<div class="fc-map " uib-collapse="coupon.coupon_data.isMapCollapsed" >
</div>
</div>
<div class="clearfix">
<div class="buttons add_to_my_coupones pull-right">
<button ng-if="coupon.coupon_data.in_wallet " type="button" class="btn btnr btnp btni" ng-click='couponConditions(coupon.coupon_data.slug)'>{{::'in_my_coupons'| translate}}</button>
<a ng-if="!coupon.coupon_data.in_wallet && key=='challenges' " href='{{absolute_url}}/{{lang}}/coupons/{{coupon.coupon_data.slug}}/{{coupon.coupon_data.challenges.title}}' class="btn btnr btnp btni" >ابدء التحدي</a>
<button ng-if="!coupon.coupon_data.in_wallet && key!='challenges'" analytics-on="click" analytics-event="addToMyCoupons" analytics-properties="{coupon_id:{{coupon.coupon_data.coupon_id}}}" ng-click="addToMyCoupons(coupon.coupon_data)" class="btn btnr btnp btni icon-heart">{{::'add_to_my_coupones'| translate}}</button>
</div>
<div class="pull-left">
<i class="icon-calendar"></i>
<label class="srm">{{::'available_to' | translate}}</label>
<!-- <fc-countdown date='coupon.coupon_data.available_to.date'></fc-countdown> -->
</div>
</div>
<div class="fc-couponComments" >
<!-- <span>{{coupon.comments.length}} {{::'comments'|translate}}</span> -->
<button ng-init="isCollapsed = true;" ng-click="isCollapsed = !isCollapsed;"><i class="icon-comment-1"></i> </button>
<ul uib-collapse="isCollapsed" >
<li>
<img src="{{ currentUser?absolute_url+'/images/users/50x50/'+currentUser.picture:absolute_url+'/images/user.png'}}"/>
<div class="userComment">
<textarea ng-model="addComment.newComment" ng-enter="sendComment(coupon)"></textarea>
</div>
</li>
<li ng-repeat="comment in coupon.coupon_data.comments track by $index">
<img ng-src="{{::absolute_url}}/images/users/50x50/{{::comment.user.picture}}"/>
<p>
<label>{{::comment.user.firstname}} {{::comment.user.lastname}}</label>
<span> {{::comment.comment}} </span>
<label>{{::comment.created_at}}</label>
</p>
</li>
</ul>
</div>
</div>
</div>
home controller js :
var url = user ? "user/home/coupons" : "home/coupons";
fcDB.query(url, "GET", data).success(function(res) {
console.log('home', res);
$scope.coupon_sections = res;
});
You seem to have way too many bindings. Back in the days of Angular 1.2, I remember it was a rule of thumb to have up to 2000 bindings on the page. That's gone up by now, but I doubt it scaled exponentially.
You have 5 sections, each having numerous ng-click bindings, several nested ng-repeats which multiply this, then undetermined number of comments per coupon.
You can deal with all this in several different ways. Some of them:
join the click listeners,
lazy-load the nested comments, hours etc, if possible,
also render as html those social shares,
pre-translate content,
one-time-bind more then you do now,
reduce dependencies.
E.g. you can have one top-level ng-click instead of a dozen per section (+ possibly more in those fc-coupon repeats). So create a single top-level ng-click, and have that function find out its intended target and act accordingly. I'd say you can shave off a little bit of time, but not significant there.
Lazy-load the nested repeats - ie. don't render them immediately. When you initially render the sections, you go on and render those hours, minutes and seconds. Dunno why, but it seems like you do really a lot of those. Have those not even show until the main content is rendered. Just one way to do that is to hide the whole block with an ng-if switch and when you know you've loaded and rendered the initial 5 sections, flip one (or all) the switches and wait for those to be rendered too. You can even leave those hidden ("Loading comments...") until you know they're rendered with a single css flip. Furthermore, maybe you can do them one-at-a-time. First fully resolve the top section, then the second, then the third etc.
Remember, a lot of performance is in perceived performance.
I see you have many of the social shares that you bind to a function. Why not render those as simple HTML directly? Depending on those coupons, you can again remove a lot of bindings.
I see you use ng-translate - which introduces yet more bindings. If you know the user's language in advance, (ie. settings), maybe you can have pre-translated per-language template? E.g. If the user initially chose english, he'd load a page called home-en.html and fc-coupon-en.html instead of one generic one. Don't know if this is viable though, but considering you have a lot of nested content, it might prove useful. And you don't even have to do it by hand, I bet you can write a one-time script where you write your source template like this, and the additional build-step would generate per-language template for all this on build time.
Also try to one-time bind the nested content. E.g. ng-repeat="hour in ::hours" might help a bit. Depending on how many times you have to bind hours, minutes and seconds, there may be thousands of bindings to introduce into the page.
Reduce dependencies if you can. E.g. I see you use a "read-more" module. Maybe you can do without it. Just use a css elipsis. And have a second click listener that finds the targeted section and extends/collapses on demand. I bet that's what the original module does anyway, but yours would be one-time top-level click listener, and not a per-item angular binding that has to get sorted out.
Now, these are all guesses, because you don't show how many actual items and what exactly does it do. So take your pick on one of the suggestions, and try it or open up a new question with more details on it.
Personally, I'd think lazy-loading everything will grant you the most "perceived" performance.
I need to create templates in handlebars for an html page and the whole html should go inside of templates. For e.g. I have:
<div class= "something-pull-left-something">
<div class="someclass">
<li a href= ''>Some more info and some more divs and spans and html code</li>
</div>
</div>
and I should create a big template for the first div ''something-pull-left-something'' and smaller templates inside of it for the other items and I cant quite understand how this should happen.
Divide it up into parts as it makes sense. Try to avoid having one huge template. Instead, make one template that includes a number of other templates. You may run into performance issues but worry about that later -- it is likely not an issue.
Make main template which contains header, body and footer.
Add partials to the main template.
If you wants to use Bootstrap then you can go through this http://getbootstrap.com/components
or you can use bootstrap class
<div class="container">
<div class="col-md-12">
//code
</div>
<div class="col-md-12">
<div class="col-md-6">
//code
</div>
<div class="col-md-6">
//code
</div>
</div>
</div>