I have a SPA in Angular Material which is displaying an mdToolbar element with a hamburger menu + left sidenav. That menu at the moment resides in my index.html where I have also set-up a <ui-view> element to render the view.
Now I have a view with a mdList in it. When the user selects some items, I want a delete icon to appear in the toolbar. That delete icon should be linked to the delete action of my controller which is of course specific to the view loaded, not to index.html.
I want to know what a recommended pattern for this would be. I can think of some ways to do it, but those are ugly. I was thinking in the direction of being able to have some placeholder area in the toolbar which I can replace with contents from my view, where the element actions (ngClick) are linked to the actions of the view controller. Does anyone know a good tutorial or codepen-like example of how to do this?
Update
I've now got something implemented that I'm happy with, but it's not quite there yet. What I did is create a menuService which is injected in the controller behind my menu (it's not a separate view, could be but doesn't make a difference in this scenario). The menu controller binds to this service and other services can inject stuff in it. In my test scenario, I inject a string which is then displayed in the toolbar, all ok.
The only thing I now need to do is instead of a string, inject a button with an event handler which goes back to the controller of the view. I'm not quite certain how to do that yet.
Another update
So I created this class:
export class CommandButton {
svgSrc: string;
click: () => void;
}
which I can inject into my menuService and then binds to the menu controller. Works fine for the icon (the button appears) but as one might expect (I did), the click function doesn't work. I set this in the view controller as follows:
var deleteButton = new Services.CommandButton();
deleteButton.svgSrc = 'icons/ic_delete_24px.svg';
deleteButton.click = this.deleteLogs;
this.menuService.setButtons([deleteButton]);
And the code for this.deleteLogs is simply:
deleteLogs() {
console.log('deleting logs');
}
Code for the buttons:
<div ng-repeat="button in ctrl.buttons">
<md-button ng-click="button.click">
<md-icon md-svg-src="{{button.svgSrc}}" class="md-icon md-24"></md-icon>
</md-button>
</div>
What I hoped for is that this would trigger the deleteLogs method in the view controller, but that's not the case. I need data from the view as that is where the items are selected. As far as I can see there's just nothing happening so the binding fails somewhere. What would be a good way to make sure the click event makes to to the view controller function? I could do a $rootscope.$broadcast but that feels hacky.
Last update
Never mind, I found my own bug. The binding of the event was incorrect, should have been (note the parenthesis):
<md-button ng-click="button.click()">
In the meantime I've figured out a nice way to do this. The post itself now also contains the answer.
Related
I am new to angular. i wanted to change the page content dynamically or may be show a new component with new content in it. i have cards on my website. please refer to the link
Cards
i want, to change the content of the page and show different content on each button clicked on card. i have already created a method and what to right in it.?
Component.html
Go somewhere
component.ts
onFirstClick() {
}
Do i need to create a new component to show new content. what should i do? please help
Well depends on what you want to change dynamically, but Angular is really good in it anyhow. For example, if you want to switch the text of the button on the first click you could do:
component.ts:
buttonTxt: string = 'Click me';
onFirstClick() {
this.buttonTxt = 'Button Clicked';
}
component.html:
{{buttonTxt}}
Changing dynamically what's on the page is the kind of thing angular is good and there are a bunch of different ways: ngIf*(Hide or show html component according to boolean variable on ts) and much more.
You can read a bit more about it here: https://medium.com/#DenysVuika/dynamic-content-in-angular-2-3c85023d9c36
The code at this plnkr has a modal which pops up when a user clicks on a "Click to take quiz" button which calls a controller method that in turn calls a modal service. To get the plnkr to work, click anywhere in the code and press the space bar to add white space in a way that does not effect syntax. This will trigger plnkr to re-initialize the app and make the modal pop up after you click the button.
The problem is that the text printed in the modal does not update dynamically when timeLeft variable counts down. And also, the user's button click does not update the quizAnswer variable. In short, the modal is not able to talk interactively with the calling controller and view.
What specific changes need to be made to the plnkr to get the modal text to show the dynamic countdown, and to get the modal buttons to change the value of the $scope.quizAnswer variable?
Also, I have been carefully reading the documentation at this link. I think that the answer may be related to:
1.) $uibModal's options parameter passed in open(options) contains the parameter scope that defines the parent scope to be used for the modal's content, and also property bindToController which, when set to true, binds the scope property to a specific controller defined by controllerAs.
2.) The open(options) method returns a modal instance, which includes close(result) and dismiss(reason).
I suspect that the solution lies in these methods and parameters, but I am looking for good examples and would appreciate some experienced eyes looking at this problem.
NOTE: The solution to this came in the comments below the accepted answer, especially the link to another posting that contains 2 lines of code for emitting the modal button click's results back to the parent controller.
You have a number of issues.
First, takeQuiz at navigation.js - line 16, should be attached to $scope, not this, since this will mutate depending on context.
Second, $scope.$apply and $scope.$digst(); at navigation.js - lines 29/30 are unnecessary since you will already be in a digest cycle. They should be removed else they'll trigger an error.
Finally (and this is the meat of your issue), you are misunderstanding how modal options are bound across when creating a modal instance. It is NOT two-way binding; it is a single extends from one object to another. As a result, trying to bind to the options (or creating a concatenated string with the timeRemaining) will not update once it's bound across.
Instead, one possibility is to create an event handler inside of the modal and broadcast on each tick, updating the modal. In addition, if you pass the body text as prepend and append text, it is easier to insert your timestamp value:
You will need to inject (and broadcast from) $rootScope in your navigationController, since the modalService is registered somewhere very high in the scope chain.
On each tick, broadcast the time remaining navigation.js:
$rootScope.$broadcast('timeRemainingTick', $scope.timeRemaining);
In your modalService.js, register to receive the event inside of the controller assignment:
var timeRemainingUnbind = $scope.$on('timeRemainingTick', function(event, newTick) {
$scope.modalOptions.timeRemaining = newTick;
});
Finally, make sure that you unbind the event by calling timeRemainingUnbind() in the close events of your modal to prevent memory leaks:
$scope.modalOptions.ok = function (result) {
timeRemainingUnbind();
$modalInstance.close(result);
};
$scope.modalOptions.close = function (result) {
timeRemainingUnbind();
$modalInstance.dismiss('cancel');
};
See my working forked plunker here
I'm working on my first Ember.js project and I've to deal with the current problem:
I have a "press" page which has more contents. In ember, there are two routes - let's call it "abouts" for whole page and "about" for each content on a page. Basically, there are (currently) 7 pictures/items with titles etc. When you click on each of those, clicked picture/press gets rendered and opened. This all works perfectly.
What I want to do is - when "abouts" page gets opened, I want to automatically render latest content (right now, nothing gets rendered until you click on an image). One known solution to do that is to pass an additional argument (id) in {{linkTo}} (which is connected to the menu item) in my view, like this:
{{#linkTo 'about' 6 title='Press'}}Press{{/linkTo}}
This works, but it's not dynamic because id is hardcoded. What I want is to dynamically pass the length of "about" items minus one (in my case 7, but it will grow). Is there any way to get length of items "about" items? Maybe in ApplicationRoute or somehow?
Or do you maybe have any other idea of how to solve this? Simply, how to render some content by default?
I'm also attaching two image, to maybe be more clear about what I want to do.
I've solved this a little bit different. Here's the solution.
With {{#linkTo}}, I've generated link to root page, like this:
{{#linkTo 'abouts' title='Press'}}Press{{/linkTo}}
In AboutsRoute, I've added redirection which is performed immediately. It looks something like this.
App.AboutsRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('about');
},
afterModel: function(abouts, transition) {
this.transitionTo('about', abouts.get('length'));
}
});
I have an emberJS object, viewed by an editablefield view, in order to be able to edit it with bindings.
I modify the view in order to be able to replace links in the text.
My problem is that if I use the inside views (Zs.RealValue) render function, it won't refresh on each update, like the simple {{value}} would do, only if I erase the text and after erase the first change.
I have a simple example here:
Steps to do: double click on one of the edit fields, the edit box appears, try modify the value, you will see, that the simple view is being updated, but not the other text view.
http://jsfiddle.net/symunona/hCjEc/7/
The problem appears because you try to implement the render function yourself in RealValue. If you change RealValue to just this:
Zs.RealValue = Ember.View.extend({
template: Ember.Handlebars.compile("{{value}}")
});
then the example works.
I'm creating an ASP.NET MVC web app and would like to use the YUI TabView (because I generally like its default look and I'm using a couple other YUI things, so the additional overhead will be comparatively small) to render a set of tabs in the master page. Here's what I want:
Each tab should render the result of a particular controller action.
Each of these controller actions will render some HTML and associated javascript.
Eventually there will be some application state to manage, but I am ignoring that at the moment just to look at the tabbed view.
What's the best way to do this?
The YUI TabView examples suggest that each tab's content is in its own div.
<div id="demo" class="yui-navset">
<ul class="yui-nav">
<li><em>Tab One Label</em></li>
<li class="selected"><em>Tab Two Label</em></li>
<li><em>Tab Three Label</em></li>
</ul>
<div class="yui-content">
<div id="tab1"><p>Tab One Content</p></div>
<div id="tab2"><p>Tab Two Content</p></div>
<div id="tab3"><p>Tab Three Content</p></div>
</div>
</div>
I don't want to do this, since I don't want to load all the content for all the tabs all at once. I'd think I'd like to catch events that let me see the tab that is being activated and then redirect to the appropriate action. It looks like the tabs' "dataSrc" attribute could help me, so I built up a test based on their dynamic example:
tabView.addTab( new YAHOO.widget.Tab({
label: 'One',
dataSrc: '/Home/Action1',
cacheData: true,
active: true
}));
tabView.addTab( new YAHOO.widget.Tab({
label: 'Two',
dataSrc: '/Home/Action2',
cacheData: true
}));
tabView.appendTo('container');
This seems to work well enough in getting to the actions, but one artifact of this is that any javascript that is emitted by my action doesn't seem to get evaluated properly... i.e., this type of thing doesn't show my alert box:
public ActionResult Action2()
{
return Content("<script type='text/javascript'>alert('test');</script>");
}
My concrete questions are:
Should I abandon YUI's TabView because it's just not the best choice for this?
Should I just catch the TabView's onBeforeTabChange event and just redirect to a view that then re-renders the master page (and thus the TabView), basically un-ajaxing the TabView?
Is there a way I can use YUI's TabView and retain the ajax behavior while getting my actions' script code to properly run?
Your content is going to be placed into the page at the appropriate place. The time for its execution is long passed. You need something like jQuery's call back function that will run a script of your choosing after the AJAX action completes. For your alert to pop, you'd have to send it with the original page request.