Adding helpers to existing controllers from plugin

plugins

#1

I’m working on a plugin right now and part of the requirements are that I display some information not only on the profile page of a user but the profile preview user-card, inside the profile main page the controller has access to a method called viewingSelf yet the same does not exist for the user-card.

How can I go about extending the user-card controller to support this method? Keep in mind this must remain isolated to my plugin and I cannot modify discourse itself in anyway.


#2

No one has any idea on how to accomplish this? This seems like it should be something pretty straight forward to do from a plugin, overriding the controller within my plugin files does not work like a template does.


(cpradio) #3

What sort of information and more importantly where do you need to display it? As plugin-outlets are usually utilized for this purpose.


(Rafael dos Santos Silva) #4

Showing a custom user field inside the user card is pretty easy, I add all the employee info on my user cards:

<!-- File discourse/plugins/discourse-plugin/assets/javascripts/discourse/connectors/user-card-metadata/show-user-card.hbs -->
<div class="falco-custom-card">
    <span class="position">{{user.user_fields.[3]}}</span>
    <span class="branch-id">{{user.user_fields.[1]}}</span>
    <span class="branch-name">{{user.user_fields.[2]}}</span>
</div>


#5

I think you are all misunderstanding the question,

Adding the buttons to the user-card is trivial but what i need is to add a method to the user-card controller.

This method specifically.

viewingSelf: function() {
return this.get(‘content.username’) === Discourse.User.currentProp(‘username’);
}.property(‘content.username’),


(cpradio) #6

Isn’t that as simple as putting a file in your plugin that does userCardController.reopen … and adding the method?

Subsequently, I highly doubt the team would be against putting that in Core. They would likely accept such a PR.


#7

Can you provide an example logic? I’ve tried a few attempts to over ride the existing user-card methods.

I’m not following what you mean by reopen, as the user-card controller itself is defined as Ember.Controller.Extend.


(cpradio) #8

Do you have an initializer for your plugin?

If so, it would be like this

import UserCard from 'discourse/controllers/user-card';

export default {
  name: 'plugin_name',
  initialize: function() {
     UserCard.reopen({
       viewingSelf: function() {
         return this.get('content.username') === Discourse.User.currentProp('username');
       }.property('content.username')
     });
  }
};

#9

Awesome, thank you that seemed to have done the trick. Is there a documentation page somewhere outlining this that I didn’t see?


(cpradio) #10

Not that I know of, it is just one of the many advantages to Ember’s framework. You can reopen existing objects and append to them.


#11

Yeah, I’m just used to being able to physically edit the controllers themselves when working within Ember so extending things via plugins is a little odd for me haha


#12

Thanks again for your assistance, though I have a question regarding how to append methods directly to the application controller itself.

I’m currently doing this…

import Application from 'discourse/controllers/application'

Application.reopen({
  canInviteToForum: function() {
    return Discourse.User.currentProp('can_invite_to_forum');
  }.property()
});

but that doesn’t seem to actually be appending the method, is there something I’m not grasping that changes when accessing the application controller vs say the user-card controller? Thanks.


(Robin Ward) #13

That should work, but due to the way ember works would only be accessible in the application template which I suspect is not what you want?

Most templates should be able to check that property by just saying {{currentUser.can_invite_to_forum}} because currentUser is injected just about everywhere.


#14

Awesome, i got it now thanks again.

My final question is since I want an action handler available in the global scope say if I’m on the discovery page then how would I make that action available? Would you suggest I append it to currentUser since that is like you said injected everywhere? Currently appending it to Discovery results in a “nothing handled action” message.

Figured this out as well, thanks again.

import DiscourseController from ‘discourse/controllers/controller’;
DiscourseController.reopen({

});


(Robin Ward) #15

If you need a global action handler we tend to put those in the application route.