I need help figuring out how to do this with Angular 7:
IF route = page, THEN SHOW item1 OR item2; else SHOW item0
Here is a visual:
/anyRoute, show item0
/route01, show item1
/route02, show item2
I am fairly new to all this and I seem to get confused with how to go about it.
Thanks in advance.
In your component
import { Routes, Router } from 'node_modules/#angular/router';
export class YourComponent implements OnInit{
constructor(public router: Router ) {
}
}
In HTML:
<ng-container *ngIf="router.url.includes('route01')">
<p>Item0</p>
</ng-container>
Related
Disclaimer: I'm new to ASP.NET Core / Razor / MVC and am starting out on the 3.0 preview.
What I want to do is have a "button" on my page that adds a new empty item to a list so that the user can input some values. From what I've read (which is quite a bit) it sounds like having a hyperlink point towards a controller is the right approach to this. I cannot get it to actually work though. Here's my code:
Link pointing to controller / action:
<a class="btn btn-success" asp-controller="Customer" asp-action="AddProduct">New Product</a>
Controller:
public class CustomerController : Controller
{
public void AddProduct()
{
var tmp = "";
}
public string Index()
{
return "This is my default action...";
}
public string Welcome()
{
return "This is the Welcome action method...";
}
}
Startup.cs routing is default:
app.UseRouting(routes =>
{
routes.MapRazorPages();
});
With this setup, if I click the start button, I see the URL change to the below, but nothing else happens (no break point is hit, for example):
https://localhost:44358/Customers/Create?action=AddProduct&controller=Customer
I have tried to adding the route to specifically to the UseRouting code, like such:
app.UseRouting(routes =>
{
routes.MapRazorPages();
routes.MapControllerRoute(
name: "Customer",
template: "{controller=Customer}/{action=Welcome}");
});
But when I do this, it seems to break, as the text color changes (from white to black) and nothing happens when I click it.
Any idea on where I'm going wrong?
I do have one more question - which is how do you access the model data from the controller?
See middle of page here: https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-4/
In Startup.cs Configure:
app.UseRouting();
app.UseEndpoints(routes =>
{
routes.MapRazorPages();
routes.MapFallbackToPage("/Home");
});
I'm trying (with partial success :( ) to retrieve full objects as observables from a collection of indexes of my firebase RTDB using angularfire2 basic methods such as list() and object() in an Ionic app.
When retrieving the list of keys for the courses a user has enrolled on I make a new query and get the full data as an observable using the object() method. I get several null in the view when loading the page for the first time but the observables are still alive, so if I make a small change in those objects in the console, the whole object is retrieved and shown in the view without any problem. Am I missing something?
Firebase RTDB root-level nodes
This is my page ts code
import { Component, ViewChild } from '#angular/core';
import { NavController, NavParams, List } from 'ionic-angular';
import { ProfileServiceProvider } from '../../providers/profile-service/profile-service';
import { MomentsFeedPage } from '../moments-feed/moments-feed';
import { CourseServiceProvider } from '../../providers/course-service/course-service';
import { AngularFireDatabase } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
/**
* Generated class for the MomentsPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#Component({
selector: 'page-moments',
templateUrl: 'moments.html',
})
export class MomentsPage{
#ViewChild('enrolledList', { read: List }) enrolledList: List;
public enrolledLis: Observable <{}>;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public courseService: CourseServiceProvider,
public userProfile: ProfileServiceProvider,
public afDB: AngularFireDatabase
) {
if(this.userProfile.currentUser) {
console.log('constructor MomentsPage');
this.enrolledLis = this.afDB.list('/userEnrollments/'+this.userProfile.currentUser.uid).snapshotChanges()
.map( res => {
let enrolled = res;
let that = this;
return enrolled.map(key =>
that.courseService.getCourseDetail(key.key).snapshotChanges()
.map(snap =>
({ key: snap.key, ...snap.payload.val() } )
)
)
}
);
}
}
goToTopicsFeed(course: any) {
this.navCtrl.push(MomentsFeedPage, {
courseId: course.key, courseName: course.name, coursePic: course.coursePic
});
}
ionViewDidLoad() {
console.log('ionViewDidLoad MomentsPage');
}
}
And this is the code for the view
<ion-header>
<ion-navbar>
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Moments</ion-title>
</ion-navbar>
</ion-header>
<ion-content no-padding fullscreen parallax-header>
<div class="header-image" style="background-image:url('./assets/imgs/lists/wishlist-1.jpg')">
<h1>Moments</h1>
</div>
<div class="main-content">
<ion-list #enrolledList>
<ion-item-sliding *ngFor="let course of enrolledLis | async" [attr.track]="(course|async)?.degree | courseTrackPipe ">
<button ion-item (click)="goToTopicsFeed(course)" >
<ion-thumbnail item-start>
<img [src]="(course|async)?.coursePic || './assets/imgs/Film-set-greyscale.jpg'" alt="Course profile pic">
</ion-thumbnail>
<h2>{{(course|async)?.name}}</h2>
<h3>{{(course|async)?.degree}}</h3>
<p>Topics info: #topics {{(course|async)?.topicsCount}} activity...</p>
</button>
</ion-item-sliding>
</ion-list>
</div>
</ion-content>
Here you can see the behaviour:
Partial processing of the observables (courses) during first call: css class in added so some rules are applied (border in blue or red)
The first object (course observable) was updated in the firebase console and updated without issues in the view
OK. I'll answer to myself: nothing wrong with the code, maybe I tested wrong. Anyway, there was something not so good in the code: returning async Observables may lead to some problems in the (click) action. Those can be solved using a *ngIf="course" block to make sure the object is got during runtime.
I'd like to start off with an apology for the poorly worded question and if this or a similar question has been answered before, but I've spent the entire day and large parts of yesterday looking for an answer with no luck so hopefully this will be ok.
I'm a complete novice to MVC (and quite new to programming in general) and am working on a "TV Guide" website, currently with hardcoded schedules etc just to get design and such in place and to learn MVC. On my index-page I will list every show, divided per channel, and as such I have this in my controller. (Trying to show only the most relevant parts)
public ActionResult Index()
{
List<ChannelVM> channelList = db.Channel.Select(x => new ChannelVM
{
Id = x.Id,
Name = x.Name,
...
}).ToList();
List<ScheduleVM> scheduleList = db.Schedule.Select(x => new ScheduleVM
{
...
ChannelId = x.ChannelId,
ChannelName = x.Channel.Name,
...
}).ToList();
var indexModel = new IndexVM
{
ChannelList = channelList,
ScheduleList = scheduleList
};
return View(indexModel);
}
In my View, I have:
#model DagensTV.Models.ViewModels.IndexVM
...
#if (Model != null)
{
foreach (var item in Model.ChannelList)
{
...
<ul>
#foreach (var show in Model.ScheduleList)
{
<li>
...
</li>
}
</ul>
...
}
}
Currently only 4 channels are hardcoded with data in a local database. Schedule is the table that has all the info I want show, and it includes a foreign key to Channel, ChannelId. With the code shown above, it creates the 4 unordered lists on the view and fills the section from Model.ChannelList correctly with the logo and so on, but in the actual schedule I of course get everything listed for every channel. I've "solved it" by making a change in the view as seen below:
#foreach (var show in Model.ScheduleList.Where(x => x.ChannelName == item.Name))
However that is not a solution I'm satisfied with as I've been told over and over to avoid that kind of code in the View, and to do everything in the controller.
In the controller I've tried adding some lambda to "filter" things similar to the solution above from the view, but to no avail.
I'm at a loss on how to proceed now so my question is, how can I filter the scheduleList so that the shows with a ChannelID of 1 go to one unordered list in the view, the shows with a ChannelID of 2 go to another etc? Any help is greatly appreciated even if it's just a nudge in the right direction. :)
You can have a property in your ChannelViewModel to hold the Schedule of the channel, and from the controller action you would return each Channel with it's Schedules populated and you would then need to only loop through those.
Your ChannelVM would need to be like:
public class ChannelVM
{
public int Id {get;set;}
public string Name {get;set;}
......
......
public List<ScheduleVM> Schedules {get;set;}
}
It would be something like:
List<ChannelVM> channelList = db.Channel.Select(x => new ChannelVM
{
Id = x.Id,
Name = x.Name,
Schedules = db.Schedule.Where(s=>s.ChannelId == x.Id)
.Select(schedule => new ScheduleVM
{
...
}).ToList();
Now in your view you would be doing something like:
foreach (var item in Model.ChannelList)
{
...
<ul>
#foreach (var show in item.ScheduleList)
{
<li>
...
</li>
}
</ul>
...
}
Note: This is just to give you the approach idea how you can do it, you would need to adjust your ViewModel to get it working.
Hope it helps!
I have a question related to inheritance and displaying modal dialogs. I am using Angular Dart and am not sure how to accomplish what I want. I have been unsuccessful in finding any useful examples.
I currently have an abstract base Task class and a TaskA class that extends the Task class. Both are NgTwoWay components. The main html is just a simple form with a button on it. When the button is clicked, I want a modal dialog to display. This modal will either be one from TaskA or TaskB depending on which type of task was created. The problem occurs when I try to show the modal from the extended class. I don't think the TaskAComponent is getting created so the html is not accessible or does not exist yet. I have also tried making the TaskComponent abstract and TaskAComponent extending from it but then none of the task html shows up.
Here is the code I currently have.
task_component.dart
abstract class Task {
Scope _scope;
Task([this._scope]) {
}
void displayProperties();
}
#Component(
visibility: Directive.CHILDREN_VISIBILITY,
selector: 'task',
templateUrl: '../lib/components/task_component.html',
publishAs: 'taskCmp',
useShadowDom: false)
class TaskComponent {
#NgTwoWay('task')
Task task;
Scope _scope;
TaskComponent([this._scope]) {
}
void displayProperties() {
task.displayProperties();
}
}
task_A_component.dart
class TaskA extends Task {
Scope _scope;
TaskA([this._scope]) {
Modal.use();
}
void displayProperties() {
Modal myWindow;
var readComplete = querySelector('#taskA_Modal');
myWindow = new Modal(readComplete);
myWindow.show();
}
}
#Component(
visibility: Directive.CHILDREN_VISIBILITY,
selector: 'taskA',
templateUrl: '../lib/components/task_A_component.html',
publishAs: 'taskACmp',
useShadowDom: false)
class TaskAComponent {
#NgTwoWay('taskA')
TaskA taskA;
Scope _scopeA;
TaskAComponent([this._scopeA]) {
Modal.use();
}
void displayProperties() {
taskA.displayProperties();
}
}
Does anyone have any ideas what I am doing wrong? Is it possible to accomplish what I am trying to do?
Use ng-switch which conditionally create the component of your choice
EX:
<div ng-switch="ctrl.task.runtimeType">
<div ng-switch-when="Task">
<task task="ctrl.task"></task>
</div>
<div ng-switch-when="TaskA">
<taskA taskA="ctrl.task"></taskA>
</div>
</div>
My answer is very late but i hope it can help
How do I create tabbed navigation with the "Current" tab highlighted in the UI?
Before MVC I looked at the file path and figured out which tab was currrent. Now it's a lot easier, you can assign the current tab based on the current controller.
Check it out ...
Most of the work happens in the usercontrol.
public partial class AdminNavigation : ViewUserControl
{
/// <summary>
/// This hold a collection of controllers and their respective "tabs." Each Tab should have at least one controller in the collection.
/// </summary>
private readonly IDictionary<Type, string> dict = new Dictionary<Type, string>();
public AdminNavigation()
{
dict.Add(typeof(BrandController), "catalog");
dict.Add(typeof(CatalogController), "catalog");
dict.Add(typeof(GroupController), "catalog");
dict.Add(typeof(ItemController), "catalog");
dict.Add(typeof(ConfigurationController), "configuration");
dict.Add(typeof(CustomerController), "customer");
dict.Add(typeof(DashboardController), "dashboard");
dict.Add(typeof(OrderController), "order");
dict.Add(typeof(WebsiteController), "website");
}
protected string SetClass(string linkToCheck)
{
Type controller = ViewContext.Controller.GetType();
// We need to determine if the linkToCheck is equal to the current controller using dict as a Map
string dictValue;
dict.TryGetValue(controller, out dictValue);
if (dictValue == linkToCheck)
{
return "current";
}
return "";
}
}
Then in your .ascx part of the usercontol call into the SetClass method to check the link against the dict. Like so:
<li class="<%= SetClass("customer") %>"><%= Html.ActionLink<CustomerController>(c=>c.Index(),"Customers",new{#class="nav_customers"}) %></li>
All you need now is the CSS to highlight your current tab. There are a bunch of different ways to do this, but you can get started with some ideas here: http://webdeveloper.econsultant.com/css-menus-navigation-tabs/
Oh, and don't forget to put the usercontrol on your page (or MasterPage) ...
<% Html.RenderPartial("AdminNavigation"); %>
I wrote some simple helper classes to solve this problem. The solution looks att both which controller that is used as well as which action in the controller.
public static string ActiveTab(this HtmlHelper helper, string activeController, string[] activeActions, string cssClass)
{
string currentAction = helper.ViewContext.Controller.
ValueProvider.GetValue("action").RawValue.ToString();
string currentController = helper.ViewContext.Controller.
ValueProvider.GetValue("controller").RawValue.ToString();
string cssClassToUse = currentController == activeController &&
activeActions.Contains(currentAction)
? cssClass
: string.Empty;
return cssClassToUse;
}
You can the call this extension method with:
Html.ActiveTab("Home", new string[] {"Index", "Home"}, "active")
This will return "active" if we are on the HomeController in either the "Index" or the "Home" action. I also added some extra overloads to ActiveTab to make it easier to use, you can read the whole blog post on: http://www.tomasjansson.com/blog/2010/05/asp-net-mvc-helper-for-active-tab-in-tab-menu/
Hope this will help someone.
Regards,
--Tomas
One method I am using on a current project - this also helps for other page-specific CSS needs.
First, an HTML helper that returns a string that represents the current controller and action:
public static string BodyClass(RouteData data) {
return string.Format("{0}-{1}", data.Values["Controller"], data.Values["Action"]).ToLower();
}
Then, add a call to this helper in your master page:
<body class="<%=AppHelper.BodyClass(ViewContext.RouteData) %>">
...
</body>
Now, you can target specific pages with your CSS. To answer your exact question about navigation:
#primaryNavigation a { ... }
.home-index #primaryNavigation a#home { ... }
.home-about #primaryNavigation a#about { ... }
.home-contact #primaryNavigation a#contact { ... }
/* etc. */
MVC's default Site.css comes with a class named 'selectedLink' which should be used for this.
Add the following to your ul list in _Layout.cshtml:
#{
var controller = #HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
}
<ul id="menu">
<li>#Html.ActionLink("Home", "Index", "Home", null, new { #class = controller == "Home" ? "selectedLink" : "" })</li>
...
</ul>
I know this is not clean. But just a quick and dirty way to get things rolling without messing with partial views or any of that sort.