I have one requirement. Can you anybody suggest the possible ways to achieve it.
I want to change the theme of my application based on the URL passed in every routes.I am using the below technologies.
- Frontend : Angular JS
- Backend : Node.js
eg: localhost/x/about
localhost/y/about
I achieved these via cookies by passing the param using localtion.search at the time of login. But I need that theme param in all the routes.Based on that theme need to change.Can anyone suggest the possible ways.
app.js
app = angular.module('themeApp', ['ngRoute'])
app.config(function($routeProvider){
$routeProvider
.when('/',{
templateUrl: 'home.html'
})
.when('/:id/about',{
templateUrl: 'about.html'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('themeController', function ($scope, $routeParams) {
console.log($routeParams.id);
// set the default theme
$scope.css = $routeParams.id;
});
menu.html (it is not complete, confuse here. please correct, how to call)
<li>
About
</li>
<li>
Home
</li>
index.html
<html ng-app="themeApp" ng-controller="themeController">
<head>
<!-- pull in css based on angular -->
<link rel="stylesheet" ng-href="css/{{css}}.css">
</head>
<body>
<div ng-view></div>
<!-- bring in JS and angular -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.14/angular.js"> </script>
<script rc="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.14/angular-route.js"></script>
<script src="app.js"> </script>
</body>
</html>
css/
it contains the three files,
- red.css
body{
background-color: red;
color: #333;
font-family: "Source Sans Pro",Calibri,Candara,Arial,sans-serif;
font-size: 15px;
}
green.css
body{
background-color: green;
color: #333;
font-family: "Source Sans Pro",Calibri,Candara,Arial,sans-serif;
font-size: 15px;
}
blue.css
body{
background-color: blue;
color: #333;
font-family: "Source Sans Pro",Calibri,Candara,Arial,sans-serif;
font-size: 15px;
}
The quick and simple answer would be to use $rootScope. $rootScope is available to all controllers, but like all global variables should be used sparingly.
Here's a good post explaining $rootScope. http://www.dotnet-tricks.com/Tutorial/angularjs/UVDE100914-Understanding-AngularJS-$rootScope-and-$scope.html
Basically if you're using it on your two controllers for pages x and y
app.controller('login',['$scope','$rootScope', function ($scope,$rootScope) {
$rootScope.foo='bar';
}]);
app.controller('xCtrl',['$scope','$rootScope', function ($scope,$rootScope) {
$scope.lorem=$rootScope.foo;
console.log($scope.lorem); //bar
}]);
app.controller('yCtrl',['$scope','$rootScope', function ($scope,$rootScope) {
$scope.ipsum=$rootScope.foo;
console.log($scope.ipsum); //bar
}]);
Can then use them in your HTML markup as normal.
Using $rootScope is much simpler, but if you wanted to use the router to pull down the id each time, it is also possible.
app.config(function($routeProvider){
$routeProvider
.when('/',{
controller: 'indexController',
templateUrl: 'view/index.html'
})
.when('/:id/about',{
controller: 'xCtrl',
templateUrl: 'view/x.html'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('xCtrl',['$scope','$routeParams', function($scope,$routeParams){
$scope.foo=$routeParams.id;
}]);
If you have a lot more pages than just /about I could imagine this getting a bit tricky with the routing.
You could even couple it with root scope then pass it around to your other controllers.
app.controller('xCtrl',['$scope','$rootScope','$routeParams', function($scope,$rootScope,$routeParams){
$rootScope.foo=$routeParams.id;
$scope.lorem=$rootScope.foo;
}]);
--EDIT based on comment--
I might need some code to be sure of what you're after, but perhaps this clarifies?
URL: mysite.com/blue/about
app.config(function($routeProvider){
$routeProvider
.when('/',{
controller: 'indexController',
templateUrl: 'view/index.html'
})
.when('/:id/about',{
controller: 'xCtrl',
templateUrl: 'view/x.html'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('xCtrl',['$scope','$routeParams', function($scope,$routeParams){
$scope.theme=$routeParams.id;
}]);
HTML
<div ng-controller="xCtrl">
<div ng-class="{{theme}}">
My theme is {{theme}}.
</div>
</div>
CSS
.blue
{
background-color: blue;
}
.green
{
background-color: green;
}
Related
No fancy webpack, simple Vue custom element with some global css and some inline css for overrides.
I would like to use some styling library, like from getbootstrap.com and have it change styles inside custom element.
https://jsfiddle.net/Deele/6xk1atrn/25/
<div class="btn bg-info">Zero</div>
<test-widget id="One"></test-widget>
<test-widget id="Two"></test-widget>
const TestWidget = Vue.defineCustomElement({
props: {
id: String
},
data: () => {
return {
message: 'Test'
}
},
emits: {},
template: `<div class="btn bg-info">{{id}} {{message}}</div>`,
styles: [`div { color: green; }`]
})
customElements.define('test-widget', TestWidget)
.bg-info {
background-color: red!important;
}
Was expecting divs inside rendered elements would be styled as buttons, but it does not work!?
From what I have found in the internet, it has something to do with Shadow DOM not inheriting any global styles.
Please, tell me if there is a solution to this approach? I would like to create small widgets for my website using Vue.js, but this hurdle creates fatal limitation.
Custom elements defined using the Vue API always use a shadow DOM, so they are isolated from the parent document and any global styles in the app.
So to make it happen, You can inject the bootstrap styles or any global style url's in the styles option by using #import statement.
Live Demo :
const TestWidget = Vue.defineCustomElement({
props: {
id: String
},
data: () => {
return {
message: 'Test'
}
},
template: `<div class="btn bg-info">{{id}} {{message}}</div>`,
styles: [`#import url("https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css"); div { color: green; }`]
});
customElements.define('test-widget', TestWidget);
<script src="https://unpkg.com/vue#next"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css"/>
<div class="btn bg-info">Zero</div>
<test-widget id="One"></test-widget>
<test-widget id="Two"></test-widget>
I am new to next js.
I have _app.tsx page:
import '../styles/antd.css'
import '../styles/globals.css'
import type { AppProps } from 'next/app'
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
</>
)
}
export default MyApp
Problem is that styles - import '../styles/antd.css' are loaded as a external request in production run /_next/static/css/fffc165f54adb267.css it mean that there is a one second blink lag during the styles loading. Is there any better way how to load styles in my base page? Without external request for styles?
Next.JS's docs when talking about importing CSS states
In production, all CSS files will be automatically concatenated into a single minified .css file.
With SSR, the mark-up is sent to the user's DOM, which will have a link tag to your styles, the user will need to fetch, and parse styles before they render, which is what causes that flash you're talking about.
Use Styled-JSX to avoid this.
Styled-JSX will add the CSS render on the server with the rest of the content, and when served load with everything else instantly* Here's an example from their docs
function HelloWorld() {
return (
<div>
Hello world
<p>scoped!</p>
<style jsx>{`
p {
color: blue;
}
div {
background: red;
}
#media (max-width: 600px) {
div {
background: blue;
}
}
`}</style>
<style global jsx>{`
body {
background: black;
}
`}</style>
</div>
)
}
export default HelloWorld
I'm using critical to generate Critical path CSS for my site. I have a gulp task set up as follows:
gulp.task('critical-css', function () {
critical.generate({
base: 'CriticalCss/',
inline: false,
src: 'index.html',
dest: 'critical.min.css',
minify: true,
width: 320,
height: 480
}).then(function (output) {
// Take 'output' and place it in masterpage
});
});
I'm wondering if it's possible to take the value of the output parameter, which is my Critical CSS, and inject this into my Masterpage through gulp inside of an inline <style> tag?
I've tried using my Masterpage as the dest property however this doesn't work as the source file is different due to it being made up of the server generated HTML. I cannot use the Masterpage as the source file either as it's not a true representation of what is rendered to the user for obvious reasons.
Would something like html-replace work for this?
So I managed to do this with gulp-inject, it allows you to dynamically inject files or file contents into your pages pretty easily.
Here's my final gulp task:
gulp.task('critical-css', function () {
critical.generate({
base: 'CriticalCSS/',
inline: false,
src: 'index.html',
dest: 'critical.min.css',
minify: true,
width: 320,
height: 480
})
.then(function (output) {
gulp.src('./CMSTemplates/Web/MasterPages/Root.Master')
.pipe(inject(gulp.src(['./CriticalCSS/*.css']), {
starttag: '<!-- inject:{{path}} -->',
transform: function (filePath, file) {
return '<style type="text/css">'
+ output +
'</style>';
}
}))
.pipe(gulp.dest('./CMSTemplates/Web/MasterPages'));
});
});
It ends up replacing this:
<!-- inject:/CriticalCSS/critical.min.css-->
<!-- endinject -->
With this:
<!-- inject:/CriticalCSS/critical.min.css-->
<style type="text/css">#charset "UTF-8";img{max-width:100%}img{border:0}body{padding:0}img{height:auto}html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;box-sizing:border-box}header,nav{display:block}img{-ms-interpolation-mode:bicubic;display:inline-block;vertical-align:middle}input{color:inherit;font:inherit;margin:0}body{-webkit-font-smoothing:antialiased}a,i{line-height:inherit}ul{line-height:1.6}input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}.foundation-mq{font-family:"small=0em&medium=40.125em&large=64.125em&xlarge=75em&xxlarge=90em"}*,::after,::before{box-sizing:inherit}body{margin:0;-moz-osx-font-smoothing:grayscale}.clearfix::after{clear:both}div,form,li,ul{margin:0;padding:0}ul{margin-left:1.25rem}ul{margin-bottom:1rem}i{font-style:italic}a{background-color:transparent;text-decoration:none}a img{border:0}ul{list-style-position:outside}li{font-size:inherit}ul{list-style-type:disc}.menu{list-style-type:none}.button{text-align:center}.menu>li,.menu>li>a i,.menu>li>a i+span{vertical-align:middle}.button,.menu>li>a{line-height:1}.button{-webkit-appearance:none;border-radius:0;margin:0 0 1rem;background-color:#2199e8}.menu a{margin-bottom:0}.menu{margin:0}.menu>li>a{display:block;padding:.7rem 1rem}.menu>li>a i{margin-right:.25rem;display:inline-block}.menu>li{display:table-cell}.menu.vertical>li{display:block}body,html{height:100%}#media screen and (max-width:64.0625em){.show-for-large{display:none!important}}.clearfix::after,.clearfix::before{content:' ';display:table}body,html{background:#eeedea}body,html{color:#000;letter-spacing:0}body,html{font:100%;font-family:"Trebuchet MS";font-size:100%;font-style:normal;line-height:1.5rem}a{color:#000}.header__wrap .menu a,.header__wrap .menu span{font-family:ApercuProBold,"Trebuchet MS"}#font-face{font-family:ApercuProBold;src:url(/web/css/fonts/ApercuPro-Bold-Web.eot);src:url(/web/css/fonts/ApercuPro-Bold-Web.eot?#iefix) format("embedded-opentype"),url(/web/css/fonts/ApercuPro-Bold-Web.woff2) format("woff2"),url(/web/css/fonts/ApercuPro-Bold-Web.woff) format("woff"),url(/web/css/fonts/ApercuPro-Bold-Web.ttf) format("truetype"),url(/web/css/fonts/ApercuPro-Bold-Web.svg#ApercuPro-Bold) format("svg");font-weight:700;font-style:normal}#font-face{font-family:icomoon;src:url(/web/css/fonts/icomoon/icomoon.eot?h3styg);src:url(/web/css/fonts/icomoon/icomoon.eot?h3styg#iefix) format("embedded-opentype"),url(/web/css/fonts/icomoon/icomoon.ttf?h3styg) format("truetype"),url(/web/css/fonts/icomoon/icomoon.woff?h3styg) format("woff"),url(/web/css/fonts/icomoon/icomoon.svg?h3styg#icomoon) format("svg");font-weight:400;font-style:normal}.header__menu .destinations-menu-item:after{content:""!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header{z-index:999;width:100%;height:45px;position:fixed;background:#000}.header__wrap{position:relative;height:100%}.header__section{width:auto;display:inline-block;height:100%}.header__wrap .menu a{padding-right:.5rem;padding-left:.5rem;text-decoration:none}.header__wrap .menu a,.header__wrap .menu span{color:#fff;font-size:.875rem;letter-spacing:0}.header__logo{position:relative;top:10px;float:left}.header__logo .logo{display:block}#media only screen and (min-width:40.063em) and (max-width:64em){.header__logo{width:60px}}.header__menu{position:relative;width:100%;height:100%}.header__menu ul.menu{position:absolute;display:none}.header__menu .parallel-logo>i{display:none}.header__menu .parallel-logo>span{text-indent:100%;white-space:nowrap;overflow:hidden;margin-left:10px;background-image:url(/web/images/logos/logo_parallel.svg);background-repeat:no-repeat;width:62px;height:13px;display:inline-block;position:relative;top:1px}.header__menu .destinations-menu-item{position:relative;padding-right:12px!important;margin-right:12px!important;text-decoration:none}.header__menu .destinations-menu-item:after{font-family:icomoon;font-size:.75rem;color:#fff;position:absolute;top:13px;right:-3px;display:inline-block;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}#-moz-document url-prefix(){.header__wrap .parallel-logo{padding-top:14px}.header__menu .destinations-menu-item:after{top:15px}}#media only screen and (min-width:40.063em) and (max-width:64em){.header__menu .destinations-menu-item:after{top:11px}}#media only screen and (min-width:40.063em) and (max-width:64em){.header__menu{height:90px;width:100%}}#media (min-width:1024px) and (max-width:1200px){.header__menu ul.menu{padding-left:10px}}.button{-webkit-transform:perspective(1px) translateZ(0);box-shadow:0 0 1px transparent}.form .error{border:2px solid #e85460!important}.button:after{content:""!important;line-height:inherit}.button{color:#000;display:inline-block;overflow:hidden;letter-spacing:0;vertical-align:middle}.button,.button:after{font-size:.875rem}.button{background:#f7e066;font-family:ApercuProBold,"Trebuchet MS";padding:17px 24px 17px 20px;margin-bottom:.3125rem;border:none;text-transform:uppercase;transform:perspective(1px) translateZ(0);position:relative}.button:after{font-weight:400;text-transform:none;speak:none;font-style:normal;font-variant:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.button:after{font-family:icomoon;color:#000}.button:before{content:"";z-index:-1;height:3px;left:0;bottom:0}.button:before{position:absolute;right:100%;background:#000}.button:after{position:absolute;right:19px;height:14px;top:50%;margin-top:-7px}.newsletter-modal span.error{color:#fff;background:#e85460;padding:12px 0 12px 40px;line-height:1;position:relative;width:100%;float:left;margin-bottom:20px}.newsletter-modal span.error::before{content:'!';width:20px;height:20px;display:block;position:absolute;border:2px solid #fff;border-radius:50%;text-align:center;left:12px;top:10px;font-size:15px}select.uppercase option{text-transform:uppercase}#destinationDropdown.destination-dropdown-menu{z-index:99999;background:#eeedea;color:#000;position:absolute;top:90px;left:22px;padding:15px;display:none;border:1px solid #ddd}#destinationDropdown.destination-dropdown-menu ul{padding:0;margin:0;top:0}#destinationDropdown.destination-dropdown-menu li{outline:0}#destinationDropdown.destination-dropdown-menu li a{text-transform:uppercase;color:#000;font-family:ApercuProBold,"Trebuchet MS";font-size:1.125rem;outline:0;padding:0}#destinationDropdown.destination-dropdown-menu .button{margin-bottom:0;margin-top:15px;width:100%;text-align:left}#destinationDropdown.destination-dropdown-menu .menu-item{margin-bottom:5px}#destinationDropdown.destination-dropdown-menu .menu-item span{color:#000;font-size:20px;padding:0 7px}#stickyForm .select select option{color:#000}#stickyForm .form input{width:100%;margin-bottom:.3125rem}</style>
<!-- endinject -->
In my Masterpage file, hopefully this helps someone else.
I have a form page that I'm working on and the basic AngularJS structure is working. When the user selects a particular font, I want all page elements to change to that font. In my stylesheet, I am using the "*" selector but I can't figure out how to update that via Angular. I have attached the basic page structure code below (note that the page has more elements than this but I removed all but the H1 for this question). Any ideas?
<!doctype html>
<html ng-app="theapp">
<head>
<title>App</title>
<style type="text/css">
* {
font-family: sans-serif;
font-size: 12pt;
}
</style>
</head>
<body ng-controller="FormController as form">
<h1>Hello</h1>
<form name="theForm">
<select ng-model="font" ng-options="font.face for font in fonts"></select>
</form>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript">
(function () {
angular.module("theapp", [])
.controller("FormController", ["$scope", function ($scope) {
$scope.fonts = [
{ face: "sans-serif" },
{ face: "Arial" },
{ face: "Tahoma" },
{ face: "Trebuchet MS" },
{ face: "Verdana" },
{ face: "serif" },
{ face: "Times" },
{ face: "Georgia" },
{ face: "monospace" },
{ face: "Courier" }
];
$scope.font = $scope.fonts[0];
}]);
})();
</script>
</body>
</html>
You can use ng-style in your markup and link it to the scope.font variable.
Have a look at the docs: https://docs.angularjs.org/api/ng/directive/ngStyle
I haven't tried it, but you could add a div under the body such that <div ng-style="style"> and in your controller you do $scope.style = {"font-family": $scope.font}.
Add style="font-family:{{font.face}}" to the body tag.
I made a plunkr to demonstrate
Thank you [orange] and [nilsK] for your suggestions.
Both are good ideas but still don't do quite what I need.
In the end, I decided to just use jQuery to update the $("*").css() attribute.
(We're already using jQuery anyway so I'm not bringing in another JS library unnecessarily.)
This does exactly what I need and doesn't complicate the code.
Thanks again! :)
I want to load a specific CSS file only when a user accesses the contact.html view on my AngularJS app/site. I found this answer which almost made sense to me How to include view/partial specific styling in AngularJS The accepted answer by charlietfl reads :
Could append a new stylesheet to head within $routeProvider. For
simplicity am using a string but could create new link element also,
or create a service for stylesheets
/* check if already exists first - note ID used on link element*/
/* could also track within scope object*/
if( !angular.element('link#myViewName').length){
angular.element('head').append('<link id="myViewName" href="myViewName.css" rel="stylesheet">');
}
Biggest benefit of prelaoding in page is any background images will
already exist, and less lieklyhood of FOUC
The problem is that I do not know exactly where in my $routeProvider to add the code. charlietfl mentions where to put it in a comment which reads
not if the when for the route hasn't been called. Can put this code in
controller callback of when within the routeProvider, or perhaps
within resolve callback which likely triggers sooner
I have modified my $routeProvider following the advice. I added a resolve in the object following .when('/contact'. Here is my code
angular.module('maxmythicApp', ['ngResponsiveImages'])
.config(function ($locationProvider, $routeProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix = '!';
$routeProvider
.when('/', {
templateUrl: '/views/design.html',
controller: 'MainCtrl'
})
.when('/design', {
templateUrl: '/views/design.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: '/views/about.html',
controller: 'MainCtrl'
})
.when('/contact', {
templateUrl: '/views/contact.html',
controller: 'MainCtrl',
resolve:
if( !angular.element('link#myViewName').length){
angular.element('head').append('<link id="myViewName" href="myViewName.css" rel="stylesheet">');
}
})
.otherwise({
redirectTo: '/'
});
});
Would this work?
I made a service for it.
Important part of the code :
var head = angular.element(document.querySelector('head')); // TO make the code IE < 8 compatible, include jQuery in your page and replace "angular.element(document.querySelector('head'))" by "angular.element('head')"
if(head.scope().injectedStylesheets === undefined)
{
head.scope().injectedStylesheets = [];
head.append($compile("<link data-ng-repeat='stylesheet in injectedStylesheets' data-ng-href='{{stylesheet.href}}' rel='stylesheet' />")(scope)); // Found here : http://stackoverflow.com/a/11913182/1662766
}
head.scope().injectedStylesheets.push({href: "/url/to/style.css"});
Full code in Github : https://github.com/Yappli/angular-css-injector)
UPDATED: Here is the solution to inject(load) a specific CSS using the $routeProvider.
The solution described below is an alternative to apply different classes and page title based on the route which could be used in other situations.
For each route I've created a new key called 'bodyClass' and 'title' (but you could called anything you like it) and it looks like this:
'use strict';
var myApp = angular.module('myApp', 'ngResource'])
.config(function ($routeProvider) {
myApp.siteName = 'My Cool App';
$routeProvider
.when('/home', {
title:'Home - ' + myApp.siteName,
bodyClass: 'home',
templateUrl: 'views/home.html',
controler: 'bmsHomeCtrl'
})
.when('/contact', {
title:'Contact - ' + myApp.siteName,
bodyClass: 'contact',
templateUrl: 'views/contact.html',
controler: 'bmsContactCtrl'
})
.otherwise({
redirectTo: '/home'
});
});
Then for each $routeChangeSuccess event I change the <title> of the page and also the class of the <body>.
myApp.run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
if (current.$$route) {
$rootScope.title = current.$$route.title;
$rootScope.bodyClass = current.$$route.bodyClass;
}
});
}]);
You put the code above on the same main app.js (for example) file.
On my index.html page, which renders the views, I have the following codes to pick up the title and class:
<title>{{ title }}</title>
<body class="{{ bodyClass }}">
So if i visit the home page of my application the title tag will be
<tittle> Home - My Cool App</tittle>
and the body tag will be
<body class="home">
It's working like a charm.
I know this solution doesn't load a CSS file, but you could put those styles inside a '.contact' class that is applied only when you hit a specific route.
Not sure if solves your problem but I hope that helps or at least point you on the right direction.
For a full solution I suggest using AngularCSS.
As you already know, in Angular we can include templates (structure) and controllers (behavior) in pages and components. AngularCSS enables the last missing piece: attaching stylesheets (presentation).
Routes example:
$routeProvider
.when('/page1', {
templateUrl: 'page1/page1.html',
controller: 'page1Ctrl',
/* Now you can bind css to routes */
css: 'page1/page1.css'
})
.when('/page2', {
templateUrl: 'page2/page2.html',
controller: 'page2Ctrl',
/* You can also enable features like bust cache, persist and preload */
css: {
href: 'page2/page2.css',
bustCache: true
}
})
.when('/page3', {
templateUrl: 'page3/page3.html',
controller: 'page3Ctrl',
/* This is how you can include multiple stylesheets */
css: ['page3/page3.css','page3/page3-2.css']
})
.when('/page4', {
templateUrl: 'page4/page4.html',
controller: 'page4Ctrl',
css: [
{
href: 'page4/page4.css',
persist: true
}, {
href: 'page4/page4.mobile.css',
/* Media Query support via window.matchMedia API
* This will only add the stylesheet if the breakpoint matches */
media: 'screen and (max-width : 768px)'
}, {
href: 'page4/page4.print.css',
media: 'print'
}
]
});
Directive example:
myApp.directive('myDirective', function () {
return {
restrict: 'E',
templateUrl: 'my-directive/my-directive.html',
css: 'my-directive/my-directive.css'
}
});
You can read more about AngularCSS here:
http://door3.com/insights/introducing-angularcss-css-demand-angularjs
I think the best/simplest answer is one I left here. Someone else asked the same question, so I came up with some simple code and a small github repo to handle this scenario.